PrevUpHomeNext

Configuration and Optional Features

Boost.Parser can be used entirely on its own. If Boost is available, extra functionality provided by Boost is also available.

By default, Boost.Parser is usable entirely on its own. The only explicit opt-in use of Boost is the use of Boost.Hana. If you turn on the use of Hana, the tuple type used throughout Boost.Parser will be boost::hana::tuple instead of std::tuple. To enable this, simply define BOOST_PARSER_USE_HANA_TUPLE. The Boost.Hana tuple is much nicer, because it has an operator[], and a whole lot of very useful algorithms; you will see this operator used throughout the tutorial and examples. I encourage you to use the Hana tuple, but I realize that it is an often-unfamiliar replacement for std::tuple, which is a C++ vocabulary template, and so that is the default.

[Important] Important

Boost.Parser defines a template alias boost::parser::tuple that aliases to boost::hana::tuple by default, and std::tuple when BOOST_PARSER_DISABLE_HANA_TUPLE is defined. You can future-proof your code slightly by using boost::parser::tuple, so that the code is well-formed, whether or not BOOST_PARSER_DISABLE_HANA_TUPLE is defined. For the same reason, Boost.Parser also provides a generic boost::parser::get that works with both kinds of tuple (since std::tuple has no operator[] and boost::hana::tuple does not work with std::get).

The presence of Boost headers is detected using __has_include(). When it is present, all the typical Boost conventions are used; otherwise, non-Boost alternatives are used. This applies to the use of BOOST_ASSERT versus assert, and printing typenames with Boost.TypeIndex versus with std::typeinfo.

[Note] Note

If you want to disable the use of the C macro assert, you define BOOST_DISABLE_ASSERTS. This is true whether BOOST_ASSERT is available or not.

[Important] Important

Boost.Parser uses inline namespaces around definitions of all functions and types that use the optional Boost features; the name of the inline namespace varies depending on whether the Boost implementation is used. So if Boost.TypeIndex is available to one translation unit, but another TU must use std::typeinfo, there are no ODR violations. The exception to this is the use of BOOST_ASSERT/assert; assert macros are inherently ODR traps.

Boost.Parser automatically treats aggregate structs as if they were tuples in many cases. There is some metaprogramming logic that makes this work, and this logic has a hard limit on the size of a struct that it can operate on. There is a configuration macro BOOST_PARSER_MAX_AGGREGATE_SIZE that you can adjust if the default value is too small. Note that turning this value up significantly can significantly increase compile times. Also, MSVC seems to have a hard time with large values; I successfully set this value to 50 on MSVC, but 100 broke the MSVC build entirely.

Boost.Parser uses std::optional and std::variant internally. There is no way to change this. However, when Boost.Parser generates values as a result of the parse (see Attribute Generation), it can place them into other implementations of optional and/or variant, if you tell it to do so. You tell it which templates are usable as an optional or variant by specializing the associated variable template. For instance, here is how you would tell Boost.Parser that boost::optional is an optional-type:

template<typename T>
constexpr bool boost::parser::enable_optional<boost::optional<T>> = true;

Here's how you would do the same thing for boost::variant2::variant:

template<typename... Ts>
constexpr bool boost::parser::enable_variant<boost::variant2::variant<Ts...>> = true;

The requirements on a template used as an optional are pretty simple, since Boost.Parser does almost nothing but assign to them. For a type O to be a usable optional, you must be able to assign to O, and O must have an operator* that returns the stored value, or a (possibly cv-qualified) reference to the stored value.

For variants, the requirement is even simpler; the variant type only needs to be assignable.

[Note] Note

The only thing affected by enable_variant is printing. If your variant template can be printed with just std::cout << v (where v is a variant, obviously), then you don't need to define enable_variant for your variant template.

Boost.Parser uses std::ranges::subrange extensively. However, there is no C++17 equivalent. So, there is a boost::parser::subrange for C++17 builds. To switch between these transparently in the code, while keeping CTAD operational, Boost.Parser defines BOOST_PARSER_SUBRANGE. This is the name of the template, so if you use it in your own code you would use it like BOOST_PARSER_SUBRANGE<I> to instantiate it.

Boost.Parser allows you to debug your parsers by passing trace::on to parse(). Sometimes, your run environment does not include a terminal. If you're running Boost.Parser code in the Visual Studio debugger, you can see this trace output in the Visual Studio debugger output panel rather than in a terminal by defining BOOST_PARSER_TRACE_TO_VS_OUTPUT.


PrevUpHomeNext