• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
36 namespace mpl = boost::mpl;
37 using namespace boost::type_erasure;
38 namespace 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.
43 template<class... Sig>
44 using 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.
56 typedef boost::make_recursive_variant<
57     int,
58     double,
59     std::string,
60     std::vector<boost::recursive_variant_> >::type variant_type;
61 typedef 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.
65 typedef multifunction<void(int), void(double), void(std::string)> function_type;
66 
67 class variant_handler
68 {
69 public:
handle(const variant_type & arg)70     void handle(const variant_type& arg)
71     {
72         boost::apply_visitor(impl, arg);
73     }
set_handler(function_type f)74     void set_handler(function_type f)
75     {
76         impl.f = f;
77     }
78 private:
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>
operator ()variant_handler::dispatcher84         void operator()(const T& t) { f(t); }
85         // For a vector, we recursively operate on the elements
operator ()variant_handler::dispatcher86         void operator()(const vector_type& v)
87         {
88             boost::for_each(v, boost::apply_visitor(*this));
89         }
90         function_type f;
91     };
92     dispatcher impl;
93 };
94 
main()95 int main() {
96     variant_handler x;
97     x.set_handler(std::cout << phoenix::val("Value: ") << phoenix::placeholders::_1 << std::endl);
98 
99     x.handle(1);
100     x.handle(2.718);
101     x.handle("The quick brown fox jumps over the lazy dog.");
102     x.handle(vector_type{ 1.618, "Gallia est omnis divisa in partes tres", 42 });
103 }
104 
105 //]
106