1// Boost.TypeErasure library
2//
3// Copyright 2011 Steven Watanabe
4//
5// Distributed under the Boost Software License Version 1.0. (See
6// accompanying file LICENSE_1_0.txt or copy at
7// http://www.boost.org/LICENSE_1_0.txt)
8//
9// $Id$
10
11//[multifunction
12/*`
13 (For the source of this example see
14 [@boost:/libs/type_erasure/example/multifunction.cpp multifunction.cpp])
15
16 This example implements an extension of Boost.Function that supports
17 multiple signatures.
18
19 [note This example uses C++11 features. You'll need a
20 recent compiler for it to work.]
21 */
22
23#include <boost/type_erasure/any.hpp>
24#include <boost/type_erasure/builtin.hpp>
25#include <boost/type_erasure/callable.hpp>
26#include <boost/mpl/vector.hpp>
27#include <boost/variant.hpp>
28#include <boost/phoenix/core.hpp>
29#include <boost/phoenix/operator.hpp>
30#include <boost/range/algorithm.hpp>
31#include <algorithm>
32#include <vector>
33#include <string>
34#include <iostream>
35
36namespace mpl = boost::mpl;
37using namespace boost::type_erasure;
38namespace phoenix = boost::phoenix;
39
40// First of all we'll declare the multifunction template.
41// multifunction is like Boost.Function but instead of
42// taking one signature, it takes any number of them.
43template<class... Sig>
44using multifunction =
45 any<
46 mpl::vector<
47 copy_constructible<>,
48 typeid_<>,
49 relaxed,
50 callable<Sig>...
51 >
52 >;
53
54// Let's use multifunction to process a variant. We'll start
55// by defining a simple recursive variant to use.
56typedef boost::make_recursive_variant<
57 int,
58 double,
59 std::string,
60 std::vector<boost::recursive_variant_> >::type variant_type;
61typedef std::vector<variant_type> vector_type;
62
63// Now we'll define a multifunction that can operate
64// on the leaf nodes of the variant.
65typedef multifunction<void(int), void(double), void(std::string)> function_type;
66
67class variant_handler
68{
69public:
70 void handle(const variant_type& arg)
71 {
72 boost::apply_visitor(visitor&: impl, visitable: arg);
73 }
74 void set_handler(function_type f)
75 {
76 impl.f = f;
77 }
78private:
79 // A class that works with boost::apply_visitor
80 struct dispatcher : boost::static_visitor<void>
81 {
82 // used for the leaves
83 template<class T>
84 void operator()(const T& t) { f(t); }
85 // For a vector, we recursively operate on the elements
86 void operator()(const vector_type& v)
87 {
88 boost::for_each(rng: v, fun: boost::apply_visitor(visitor&: *this));
89 }
90 function_type f;
91 };
92 dispatcher impl;
93};
94
95int main() {
96 variant_handler x;
97 x.set_handler(std::cout << phoenix::val(t: "Value: ") << phoenix::placeholders::_1 << std::endl);
98
99 x.handle(arg: 1);
100 x.handle(arg: 2.718);
101 x.handle(arg: "The quick brown fox jumps over the lazy dog.");
102 x.handle(arg: vector_type{ 1.618, "Gallia est omnis divisa in partes tres", 42 });
103}
104
105//]
106

source code of boost/libs/type_erasure/example/multifunction.cpp