...one of the most highly
regarded and expertly designed C++ library projects in the
world.
— Herb Sutter and Andrei
Alexandrescu, C++
Coding Standards
This section presents an alternative syntax for compilers without variadic macro support.
Most modern compilers support variadic macros (notably, these include GCC,
MSVC, and all C++11 compilers). [10] However, in the rare case that programmers need to use this library
on a complier without variaidc macros, this library also allows to specify
the capture list using a Boost.Preprocessor
sequence where tokens are separated by round parenthesis ()
:
(capture1) (capture2) ... // All compilers.
Instead of the comma-separated list that we have seen so far which requires variadic macros:
capture1, capture2, ... // Only compilers with variadic macros.
For example, the following syntax is accepted on all compilers with and without
variadic macros (see also world_seq.cpp
and world.cpp
):
Boost.Preprocessor Sequence (All Compilers) |
Comma-Separated List (Variadic Macros Only) |
---|---|
void world::add_person(person const& a_person) { bool commit = false; persons_.push_back(a_person); // (1) direct action // Following block is executed when the enclosing scope exits. BOOST_SCOPE_EXIT( (&commit) (&persons_) ) { if(!commit) persons_.pop_back(); // (2) rollback action } BOOST_SCOPE_EXIT_END // ... // (3) other operations commit = true; // (4) disable rollback actions }
|
void world::add_person(person const& a_person) { bool commit = false; persons_.push_back(a_person); // (1) direct action // Following block is executed when the enclosing scope exits. BOOST_SCOPE_EXIT(&commit, &persons_) { if(!commit) persons_.pop_back(); // (2) rollback action } BOOST_SCOPE_EXIT_END // ... // (3) other operations commit = true; // (4) disable rollback actions }
|
Note how the same macros accept both syntaxes on compilers with variadic macros and only the Boost.Preprocessor sequence syntax on compilers without variadic macros. Older versions of this library used to only support the Boost.Preprocessor sequence syntax so this syntax is supported also for backward compatibility. However, in the current version of this library and on compilers with variadic macros, the comma-separated syntax is preferred because it is more readable.
Finally, an empty capture list is always specified using void
on compilers with and without variaidc macros (see also world_void.cpp
):
struct world_t { std::vector<person> persons; bool commit; } world; // Global variable. void add_person(person const& a_person) { world.commit = false; world.persons.push_back(a_person); BOOST_SCOPE_EXIT(void) { // No captures. if(!world.commit) world.persons.pop_back(); } BOOST_SCOPE_EXIT_END // ... world.commit = true; }
For reference, the following is a list of most of the examples presented in this documentation reprogrammed using the Boost.Preprocessor sequence syntax instead of comma-separated lists (in alphabetic order):
Files |
---|
[10]
A C++ compiler does not support variadic macros if the Boost.Config
macro BOOST_NO_CXX11_VARIADIC_MACROS
is defined for that compiler.