| Home | Libraries | People | FAQ | More

## Annex: No Variadic Macros

This section presents an alternative syntax for compilers without variadic macro support.

#### Sequence Syntax

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;
    }

#### Examples

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
`same_line_seq.cpp`
`scope_guard_seq.cpp`
`try_catch_seq.cpp`
`world_checkpoint_all_seq.cpp`
`world_checkpoint_seq.cpp`
`world_this_seq.cpp`
`world_tpl_seq.cpp`

[10] A C++ compiler does not support variadic macros if the Boost.Config macro `BOOST_NO_CXX11_VARIADIC_MACROS` is defined for that compiler.