Boost C++ Libraries

...one of the most highly regarded and expertly designed C++ library projects in the world. Herb Sutter and Andrei Alexandrescu, C++ Coding Standards

libs/type_erasure/example/references.cpp

// Boost.TypeErasure library
//
// Copyright 2011 Steven Watanabe
//
// Distributed under the Boost Software License Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
// $Id: references.cpp 83251 2013-03-02 19:23:44Z steven_watanabe $

#include <boost/type_erasure/any.hpp>
#include <boost/type_erasure/any_cast.hpp>
#include <boost/type_erasure/builtin.hpp>
#include <boost/type_erasure/operators.hpp>
#include <boost/mpl/vector.hpp>
#include <boost/shared_ptr.hpp>
#include <iostream>

namespace mpl = boost::mpl;
using namespace boost::type_erasure;

void references1() {
    //[references1
    /*`
        To capture by reference, we simply add a reference
        to the __placeholder.
    */
    int i;
    any<typeid_<>, _self&> x(i);
    any_cast<int&>(x) = 5; // now i is 5
    /*`
        [note `_self` is the default __placeholder, so it is
        easiest to use `_self&`.  We could use another
        __placeholder instead. __any`<`__typeid_`<_a>, _a&>` has
        exactly the same behavior.]
    */
    //]
}

void references2() {
    //[references2
    /*`
        References cannot be rebound.  Just like a built-in C++ reference,
        once you've initialized it you can't change it to point to
        something else.
        ``
            int i, j;
            any<typeid_<>, _self&> x(i), y(j);
            x = y; // error
        ``

        [note As with any other operation, `x = y` for references
        acts on `i` and `j`.  Assignment like this is legal
        if __assignable`<>` is in the Concept, but `x` would
        still hold a reference to `i`.]
    */
    //]
}

void references3() {
    //[references3
    /*`
        A reference can be bound to another __any.
    */
    typedef mpl::vector<
        copy_constructible<>,
        incrementable<>
    > requirements;

    any<requirements> x(10);
    any<requirements, _self&> y(x);
    ++y; // x is now 11
    //]
}

void references4() {
    //[references4
    /*`
        If a reference is used after the underlying object
        goes out of scope or is reset, the behavior is undefined.
    */
    typedef mpl::vector<
        copy_constructible<>,
        incrementable<>,
        relaxed
    > requirements;
    any<requirements> x(10);
    any<requirements, _self&> y(x);
    x = 1.0;
    ++y; // undefined behavior.
    //]
}

void references5() {
    typedef mpl::vector<
        copy_constructible<>,
        incrementable<>
    > requirements;
    //[references5
    /*`
        This only applies when a reference is constructed
        from a value.  If a reference is constructed from another
        reference, the new reference does not depend on the old one.
    */
    any<requirements> x(10);
    boost::shared_ptr<any<requirements, _self&> > p(
        new any<requirements, _self&>(x));
    any<requirements, _self&> y(*p); // equivalent to y(x);
    p.reset();
    ++y; // okay
    //]
}

void references6() {
    //[references6
    /*`
        Both const and non-const references are supported.
     */
    int i = 0;
    any<incrementable<>, _self&> x(i);
    any<incrementable<>, const _self&> y(x);
    /*`
        A reference to non-const can be converted to a reference
        to const, but not the other way around.  Naturally,
        we can't apply mutating operations to a const reference.

            any<incrementable<>, _self&> z(y); // error
            ++y; // error
     */
    //]
}

//[references
//` (For the source of the examples in this section see
//` [@boost:/libs/type_erasure/example/references.cpp references.cpp])
//` [references1]
//` [references2]
//` [references3]
//` [references4]
//` [references5]
//` [references6]
//]