| Home | Libraries | People | FAQ | More

## Tutorial

This section illustrates basic usage of this library.

### Local Functions

Local functions are defined using macros from the header file `boost/local_function.hpp`. The macros must be used from within a declarative context (this is a limitation with respect to C++11 lambda functions which can instead be declared also within expressions):

    #include <boost/local_function.hpp> // This library header.

    ...
    { // Some declarative context.
        ...
        result-type BOOST_LOCAL_FUNCTION(parameters) {
            body-code
        } BOOST_LOCAL_FUNCTION_NAME(name)
        ...
    }

The code expanded by the macros declares a function object (or functor) with the local function name specified by `BOOST_LOCAL_FUNCTION_NAME`. [5] The usual C++ scope visibility rules apply to local functions for which a local function is visible only within the enclosing scope in which it is declared.

The local function result type is specified just before the `BOOST_LOCAL_FUNCTION` macro.

The local function body is specified using the usual C++ statement syntax in a code block `{ ... }` between the `BOOST_LOCAL_FUNCTION` and `BOOST_LOCAL_FUNCTION_NAME` macros. The body is specified outside any of the macros so eventual compiler error messages and related line numbers retain their usual meaning and format. [6]

The local function parameters are passed to the `BOOST_LOCAL_FUNCTION` macro as a comma-separated list of tokens (see the No Variadic Macros section for compilers that do not support variadic macros):

    BOOST_LOCAL_FUNCTION(parameter-type1 parameter-name1, parameter-type2 parameter-name2, ...)

The maximum number of parameters that can be passed to a local function is controlled at compile-time by the configuration macro `BOOST_LOCAL_FUNCTION_CONFIG_ARITY_MAX`. For example, let's program a local function named `add` that adds together two integers `x` and `y` (see also `add_params_only.cpp`):

    int BOOST_LOCAL_FUNCTION(int x, int y) { // Local function.
        return x + y;
    } BOOST_LOCAL_FUNCTION_NAME(add)

    BOOST_TEST(add(1, 2) == 3); // Local function call.

If the local function has no parameter, it is possible to pass `void` to the `BOOST_LOCAL_FUNCTION` macro (similarly to the C++ syntax that allows to use `result-type function-name``(void)` to declare a function with no parameter): [7]

    BOOST_LOCAL_FUNCTION(void) // No parameter.

For example, let's program a local function that always returns `10` (see also `ten_void.cpp`):

    int BOOST_LOCAL_FUNCTION(void) { // No parameter.
        return 10;
    } BOOST_LOCAL_FUNCTION_NAME(ten)

    BOOST_TEST(ten() == 10);

### Binding Variables

Variables in scope (local variables, enclosing function parameters, data members, etc) can be bound to a local function declaration. Only bound variables, static variables, global variables, functions, and enumerations from the enclosing scope are accessible from within the local function body. The types of bound variables are deduced automatically by this library using Boost.Typeof. [8]

This library introduces the new "keyword" `bind` [9] which is used in place of the parameter type to specify the name of a variable in scope to bind (therefore, `bind` cannot be used as a local function parameter type). A variable can be bound by value:

    bind variable-name // Bind by value.

Or by reference prefixing the variable name with `&`:

    bind& variable-name // Bind by reference.

Furthermore, the "keyword" `bind` can be prefixed by `const` to bind the variable by constant value:

    const bind variable-name // Bind by constant value.

Or by constant reference:

    const bind& variable-name // Bind by constant value.

Note that when `const` is used, it must always precede `bind`. [10]

If a variable is bound by value, then a copy of the variable value is taken at the point of the local function declaration. If a variable is bound by reference instead, the variable will refer to the value it has at the point of the local function call. Furthermore, it is the programmers' responsibility to ensure that variables bound by reference survive the existence scope of the local function otherwise the bound references will be invalid when the local function is called resulting in undefined behaviour (in other words, the usual care in using C++ references must be taken for variables bound by reference).

The type of a bound variable is automatically deduced using Boost.Typeof and it is the exact same type used to declare such a variable in the enclosing scope with the following notes:

- If a bound variable was declared constant in the enclosing scope, it will always be bound by constant value or constant reference even if `bind...` is used instead of `const bind...` . However, if a bound variable was not declared constant in the enclosing scope then it will not be bound as constant unless constant binding is forced using `const bind...`. (Note that binding by constant reference is not supported by C++11 lambda functions but it is supported by this library.) [11]
- If a bound variable was declared as a reference in the enclosing scope, it will still be bound by value unless it is explicitly bound by reference using `bind&` or `const bind&`. [12]

When a variable is bound by value (constant or not), its type must be `CopyConstructible` (i.e., its must provide a copy constructor). As with passing parameters to usual C++ functions, programmers might want to bind variables of complex types by (possibly constant) reference instead of by value to avoid expensive copy operations when these variables are bound to a local function.

For example, let's program the local function `add` from the example in the Introduction section. We bind the local variable `factor` by constant value (because its value should not be modified by the local function), the local variable `sum` by non-constant reference (because its value needs to be updated with the summation result), and program the body to perform the summation (see also `add.cpp`):

    int main(void) {                            // Some local scope.
        int sum = 0, factor = 10;               // Variables in scope to bind.

        void BOOST_LOCAL_FUNCTION(const bind factor, bind& sum, int num) {
            sum += factor * num;
        } BOOST_LOCAL_FUNCTION_NAME(add)

        add(1);                                 // Call the local function.
        int nums[] = {2, 3};
        std::for_each(nums, nums + 2, add);     // Pass it to an algorithm.

        BOOST_TEST(sum == 60);                  // Assert final summation value.
        return boost::report_errors();
    }

### Binding the Object `this`

It is also possible to bind the object `this` when it is in scope (e.g., from an enclosing non-static member function). This is done by using the special symbol `this_` (instead of `this`) as the name of the variable to bind in the local function declaration and also to access the object within the local function body. [13]

| Warning

The library will generate a compile-time error if `this` is mistakenly used instead of `this_` to bind the object in the local function declaration. However, mistakenly using `this` instead of `this_` to access the object within the local function body will leads to undefined behaviour and it will not necessarily generate a compile-time error. [14] Programmers are ultimately responsible to make sure that `this` is never used within a local function.

The object `this` can be bound by value:

    bind this_ // Bind the object `this` by value.

In this case the local function will be able to modify the object when the enclosing scope is not a constant member and it will not be able to modify the object when the enclosing scope is a constant member. Otherwise, the object `this` can be bound by constant value:

    const bind this_ // Bind the object `this` by constant value.

In this case the local function will never be able to modify the object (regardless of whether the enclosing scope is a constant member or not).

Note that the object `this` can never be bound by reference because C++ does not allow to obtain a reference to `this` (the library will generate a compile-time error if programmers try to use `bind& this_` or `const bind& this_`). Note that `this` is a pointer so the pointed object is never copied even if `this` is bound by value (also it is not possible to directly bind `*this` because `*this` is an expression and not a variable name).

For example, let's program a local function `add` similar to the one in the example from the Introduction section but using a member function to illustrate how to bind the object `this` (see also `add_this.cpp`):

    struct adder {
        adder() : sum_(0) {}

        int sum(const std::vector<int>& nums, const int factor = 10) {

            void BOOST_LOCAL_FUNCTION(const bind factor, bind this_, int num) {
                this_->sum_ += factor * num; // Use `this_` instead of `this`.
            } BOOST_LOCAL_FUNCTION_NAME(add)

            std::for_each(nums.begin(), nums.end(), add);
            return sum_;
        }

    private:
        int sum_;
    };

Note that the local function has access to all class members via the bound object `this_` regardless of their access level (`public`, `protected`, or `private`). [15] Specifically, in the example above the local function updates the private data member `sum_`.

### Templates

When local functions are programmed within templates, they need to be declared using the special macros `BOOST_LOCAL_FUNCTION_TPL` and `BOOST_LOCAL_FUNCTION_NAME_TPL`: [16]

    #include <boost/local_function.hpp> // This library header.

    ...
    { // Some declarative context within a template.
        ...
        result-type BOOST_LOCAL_FUNCTION_TPL(parameters) {
            body-code
        } BOOST_LOCAL_FUNCTION_NAME_TPL(name)
        ...
    }

The `BOOST_LOCAL_FUNCTION_TPL` and `BOOST_LOCAL_FUNCTION_NAME_TPL` macros have the exact same syntax of the `BOOST_LOCAL_FUNCTION` and `BOOST_LOCAL_FUNCTION_NAME` macros that we have seen so far.

For example, let's program a local function similar to the one from the Introduction section but within a template (see also `add_template.cpp`):

    template<typename T>
    T total(const T& x, const T& y, const T& z) {
        T sum = T(), factor = 10;

        // Must use the `..._TPL` macros within templates.
        T BOOST_LOCAL_FUNCTION_TPL(const bind factor, bind& sum, T num) {
            return sum += factor * num;
        } BOOST_LOCAL_FUNCTION_NAME_TPL(add)

        add(x);
        T nums[2]; nums[0] = y; nums[1] = z;
        std::for_each(nums, nums + 2, add);

        return sum;
    }

[5] Rationale. The local function name must be passed to the macro `BOOST_LOCAL_FUNCTION_NAME` ending the function definition so this macro can declare a local variable with the local function name to hold the local function object. Therefore the local function name cannot be specified within the `BOOST_LOCAL_FUNCTION` and it must appear instead after the local function body (even if that differs from the usual C++ function declaration syntax).

[6] Rationale. If the local function body were instead passed as a macro parameter, it would be expanded on a single line of code (because macros always expand as a single line of code). Therefore, eventual compiler error line numbers would all report the same value and would no longer be useful to pinpoint errors.

[7] Rationale. The C++03 standard does not allow to pass empty parameters to a macro so the macro cannot be invoked as `BOOST_LOCAL_FUNCTION()`. On C99 compilers with properly implemented empty macro parameter support, it would be possible to allow `BOOST_LOCAL_FUNCTION()` but this is already not the case for MSVC so this syntax is never allowed to ensure better portability.

[8] Rationale. By binding a variable in scope, the local function declaration is specifying that such a variable should be accessible within the local function body regardless of its type. Semantically, this binding should be seen as an "extension" of the scope of the bound variable from the enclosing scope to the scope of the local function body. Therefore, contrary to the semantic of passing a function parameter, the semantic of binding a variable does not depend on the variable type but just on the variable name: "The variable in scope named x should be accessible within the local function named f". For example, this reduces maintenance because if a bound variable type is changed, the local function declaration does not have to change.

[9] Obviously, the token `bind` is not a keyword of the C++ language. This library parses the token `bind` during macro expansion using preprocessor meta-programming (see the Implementation section). Therefore, `bind` can be considered a new "keyword" only at the preprocessor meta-programming level within the syntax defined by the macros of this library (thus it is referred to as a "keyword" only within quotes).

[10] Rationale. The library macros could have been implemented to accept both syntaxes `const bind ...` and `bind const ...` equivalently. However, handling both syntaxes would have complicated the macro implementation without adding any feature so only one syntax `const bind ...` is supported.

[11] An historical note: Constant binding of variables in scope was the main use case that originally motivated the authors in developing this library. The authors needed to locally create a chuck of code to assert some correctness conditions while these assertions were not supposed to modify any of the variables they were using (see the Contract++ library). This was achieved by binding by constant reference `const bind&` the variables needed by the assertions and then by programming the local function body to check the assertions. This way if any of the assertions mistakenly changes a bound variable (for example confusing the operator `==` with `=`), the compiler correctly generates an error because the bound variable is of `const` type within the local function body (see also constant blocks in the Examples section).

[12] Rationale. Variables originally declared as references are bound by value unless `[const] bind&` is used so that references can be bound by both value `[const] bind` and reference `[const] bind&` (this is the same binding semantic adopted by Boost.ScopeExit). However, variables originally declared as constants should never loose their `const` qualifier (to prevent their modification not just in the enclosing scope but also in the local scope) thus they are always bound by constant even if `bind[&]` is used instead of `const bind[&]`.

[13] Rationale. The special name `this_` was chosen following Boost practise to postfix with an underscore identifiers that are named after keywords (the C++ keyword `this` in this case). The special symbol `this_` is needed because `this` is a reserved C++ keyword so it cannot be used as the name of the internal parameter that passes the bound object to the local function body. It would have been possible to use `this` (instead of `this_`) within the local function body either at the expenses of copying the bound object (which would introduce run-time overhead and also the stringent requirement that the bound object must have a deep copy constructor) or by relying on an undefined behaviour of `static_cast` (which might not work on all platforms at the cost of portability).

[14] Rationale. The local function body cannot be a static member function of the local functor object in order to support recursion (because the local function name is specified by the `BOOST_LOCAL_FUNCTION_NAME` macro only after the body so it must be made available via a functor data member named after the local function and local classes cannot have static data members in C++) and nesting (because the argument binding variable must be declared as a data member so it is visible in a local function nested within the body member function) -- see the Implementation section. Therefore, from within the local function body the variable `this` is visible but it refers to the local functor and not to the bound object.

[15] Rationale. This is possible because of the fix to C++ defect 45 that made inner and local types able to access all outer class members regardless of their access level.

[16] Rationale. Within templates, this library needs to use `typename` to explicitly indicate that some expressions evaluate to a type. Because C++03 does not allow to use `typename` outside templates, the special `..._TPL` macros are used to indicate that the enclosing scope is a template so this library can safely use `typename` to resolve expression type ambiguities. C++11 and other compilers might compile local functions within templates even when the `..._TPL` macros are not used. However, it is recommended to always use the `..._TPL` macros within templates to maximize portability.