Imported Upstream version 1.57.0
[platform/upstream/boost.git] / libs / type_erasure / example / overload.cpp
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 #include <boost/type_erasure/concept_interface.hpp>
12 #include <boost/type_erasure/param.hpp>
13 #include <boost/type_erasure/derived.hpp>
14 #include <boost/type_erasure/is_placeholder.hpp>
15 #include <boost/utility/enable_if.hpp>
16
17 namespace mpl = boost::mpl;
18 using namespace boost::type_erasure;
19
20 //[overload1
21 /*`
22     __concept_interface allows us to inject arbitrary declarations
23     into an __any.  This is very flexible, but there are some pitfalls
24     to watch out for.  Sometimes we want to use the same concept several
25     times with different parameters.  Specializing __concept_interface
26     in a way that handles overloads correctly is a bit tricky.
27     Given a concept foo, we'd like the following to work:
28
29     ``
30         any<
31             mpl::vector<
32                 foo<_self, int>,
33                 foo<_self, double>,
34                 copy_constructible<>
35             >
36         > x = ...;
37         x.foo(1);   // calls foo(int)
38         x.foo(1.0); // calls foo(double)
39     ``
40
41     Because __concept_interface creates a linear
42     inheritance chain, without some extra work,
43     one overload of foo will hide the other.
44
45     Here are the techniques that I found work reliably.
46     
47     For member functions I couldn't find a way to
48     avoid using two specializations.
49 */
50
51 template<class T, class U>
52 struct foo
53 {
54     static void apply(T& t, const U& u) { t.foo(u); }
55 };
56
57 namespace boost {
58 namespace type_erasure {
59
60 template<class T, class U, class Base, class Enable>
61 struct concept_interface< ::foo<T, U>, Base, T, Enable> : Base
62 {
63     typedef void _fun_defined;
64     void foo(typename as_param<Base, const U&>::type arg)
65     {
66         call(::foo<T, U>(), *this, arg);
67     }
68 };
69
70 template<class T, class U, class Base>
71 struct concept_interface< ::foo<T, U>, Base, T, typename Base::_fun_defined> : Base
72 {
73     using Base::foo;
74     void foo(typename as_param<Base, const U&>::type arg)
75     {
76         call(::foo<T, U>(), *this, arg);
77     }
78 };
79
80 }
81 }
82
83 /*`
84     This uses SFINAE to detect whether a using declaration is
85     needed.  Note that the fourth argument of __concept_interface
86     is a dummy parameter which is always void and is
87     intended to be used for SFINAE.
88     Another solution to the problem that I've used
89     in the past is to inject a dummy declaration of `fun`
90     and always put in a using declaration.  This is an
91     inferior solution for several reasons.  It requires an
92     extra interface to add the dummy overload.  It also
93     means that `fun` is always overloaded, even if the
94     user only asked for one overload.  This makes it
95     harder to take the address of fun.
96
97     Note that while using SFINAE requires some code
98     to be duplicated, the amount of code that has to
99     be duplicated is relatively small, since the implementation
100     of __concept_interface is usually a one liner.  It's
101     a bit annoying, but I believe it's an acceptable cost
102     in lieu of a better solution.
103 */
104
105 //]
106 //[overload2
107 /*`
108     For free functions you can use inline friends.
109 */
110
111 template<class T, class U>
112 struct bar_concept
113 {
114     static void apply(T& t, const U& u) { bar(t, u); }
115 };
116
117 namespace boost {
118 namespace type_erasure {
119
120 template<class T, class U, class Base>
121 struct concept_interface< ::bar_concept<T, U>, Base, T> : Base
122 {
123     friend void bar(typename derived<Base>::type& t, typename as_param<Base, const U&>::type u)
124     {
125         call(::bar_concept<T, U>(), t, u);
126     }
127 };
128
129 template<class T, class U, class Base>
130 struct concept_interface< ::bar_concept<T, U>, Base, U, typename boost::disable_if<is_placeholder<T> >::type> : Base
131 {
132     using Base::bar;
133     friend void bar(T& t, const typename derived<Base>::type& u)
134     {
135         call(::bar_concept<T, U>(), t, u);
136     }
137 };
138
139 }
140 }
141
142 /*`
143     Basically we have to specialize __concept_interface once for
144     each argument to make sure that an overload is injected into
145     the first argument that's a placeholder.
146     As you might have noticed, the argument types are a bit tricky.
147     In the first specialization, the first argument uses __derived
148     instead of __as_param. The reason for this is that if we used
149     __as_param, then we could end up violating the one definition
150     rule by defining the same function twice.  Similarly, we use
151     SFINAE in the second specialization to make sure that bar is
152     only defined once when both arguments are placeholders.  It's
153     possible to merge the two specializations with a bit of metaprogramming,
154     but unless you have a lot of arguments, it's probably not
155     worth while.
156 */
157
158 //]
159
160 //[overload
161 //` (For the source of the examples in this section see
162 //` [@boost:/libs/type_erasure/example/overload.cpp overload.cpp])
163 //` [overload1]
164 //` [overload2]
165 //]