|  | Home | Libraries | People | FAQ | More | 
(For the source of the examples in this section see basic.cpp)
      The main class in the library is any.
      An any can store objects
      that meet whatever requirements we specify. These requirements are passed to
      any as an MPL sequence.
    
| ![[Note]](../../../doc/src/images/note.png) | Note | 
|---|---|
| The MPL sequence combines multiple concepts. In the rare case when we only want a single concept, it doesn't need to be wrapped in an MPL sequence. | 
any<mpl::vector<copy_constructible<>, typeid_<>, relaxed> > x(10); int i = any_cast<int>(x); // i == 10
      copy_constructible
      is a builtin concept that allows us to copy and destroy the object. typeid_ provides run-time type
      information so that we can use any_cast.
      relaxed enables various
      useful defaults. Without relaxed,
      any supports exactly
      what you specify and nothing else. In particular, it allows default construction
      and assignment of any.
    
      Now, this example doesn't do very much. x
      is approximately equivalent to a boost::any.
      We can make it more interesting by adding some operators, such as operator++ and
      operator<<.
    
any< mpl::vector< copy_constructible<>, typeid_<>, incrementable<>, ostreamable<> > > x(10); ++x; std::cout << x << std::endl; // prints 11
      The library provides concepts for most C++ operators, but this obviously won't
      cover all use cases; we often need to define our own requirements. Let's take
      the push_back member, defined
      by several STL containers.
    
BOOST_TYPE_ERASURE_MEMBER((has_push_back), push_back, 1) void append_many(any<has_push_back<void(int)>, _self&> container) { for(int i = 0; i < 10; ++i) container.push_back(i); }
      We use the macro BOOST_TYPE_ERASURE_MEMBER
      to define a concept called has_push_back.
      The second parameter is the name of the member function and the last macro
      parameter indicates the number of arguments which is 1
      since push_back is unary. When
      we use has_push_back, we have
      to tell it the signature of the function, void(int).
      This means that the type we store in the any has to have a member that looks
      like:
    
void push_back(int);
      Thus, we could call append_many
      with std::vector<int>, std::list<int>,
      or std::vector<long> (because
      int is convertible to long), but not std::list<std::string> or std::set<int>.
    
      Also, note that append_many
      has to operate directly on its argument. It cannot make a copy. To handle this
      we use _self&
      as the second argument of any.
      _self is a placeholder.
      By using _self&,
      we indicate that the any
      stores a reference to an external object instead of allocating its own object.
    
      There's actually another placeholder
      here. The second parameter of has_push_back
      defaults to _self. If we wanted
      to define a const member function, we would have to change it to const _self,
      as shown below.
    
BOOST_TYPE_ERASURE_MEMBER((has_empty), empty, 0) bool is_empty(any<has_empty<bool(), const _self>, const _self&> x) { return x.empty(); }
      For free functions, we can use the macro BOOST_TYPE_ERASURE_FREE.
    
BOOST_TYPE_ERASURE_FREE((has_getline), getline, 2) std::vector<std::string> read_lines(any<has_getline<bool(_self&, std::string&)>, _self&> stream) { std::vector<std::string> result; std::string tmp; while(getline(stream, tmp)) result.push_back(tmp); return result; }
      The use of has_getline is very
      similar to has_push_back above.
      The difference is that the placeholder _self
      is passed in the function signature instead of as a separate argument.
    
      The placeholder
      doesn't have to be the first argument. We could just as easily make it the
      second argument.
    
void read_line(any<has_getline<bool(std::istream&, _self&)>, _self&> str) { getline(std::cin, str); }