5ca6414556be3615631d9806e58ee44204aa3d15
[senf.git] / senf / Utils / mpl.hh
1 // $Id$
2 //
3 // Copyright (C) 2007
4 // Fraunhofer Institute for Open Communication Systems (FOKUS)
5 // Competence Center NETwork research (NET), St. Augustin, GERMANY
6 //     Stefan Bund <g0dil@berlios.de>
7 //
8 // This program is free software; you can redistribute it and/or modify
9 // it under the terms of the GNU General Public License as published by
10 // the Free Software Foundation; either version 2 of the License, or
11 // (at your option) any later version.
12 //
13 // This program is distributed in the hope that it will be useful,
14 // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 // GNU General Public License for more details.
17 //
18 // You should have received a copy of the GNU General Public License
19 // along with this program; if not, write to the
20 // Free Software Foundation, Inc.,
21 // 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
22
23 /** \file
24     \brief mpl public header */
25
26 #ifndef HH_SENF_Utils_mpl_
27 #define HH_SENF_Utils_mpl_ 1
28
29 // Custom includes
30 #include <senf/config.hh>
31
32 //#include "mpl.mpp"
33 #include "mpl.ih"
34 //-/////////////////////////////////////////////////////////////////////////////////////////////////
35
36 namespace senf {
37 namespace mpl {
38
39     /** \defgroup senfmpl Template meta programming helpers
40      */
41
42     /** \brief Marker class for empty default values etc.
43
44         This is like Boosts \c boost::mpl::na just an empty class used as template default argument
45         to mark missing arguments
46
47         \note Don't use this as an empty base class. We may add some informative members to this.
48         \ingroup senfmpl
49      */
50     struct nil {};
51
52     /** \brief Return-value type used to implement overload selection
53
54         The senf::mpl::rv type is used together with \ref SENF_MPL_RV() to select template
55         specializations based on a set of overloads:
56
57         \code
58         template <unsigned _> struct select {};
59
60         // Case 0
61         template <>
62         struct select<0> {
63             static bool const has_int_value = true;
64             void frobble();
65         };
66         template <class T>
67         senf::mpl::rv<0> select_(int, senf::mpl::take_int<T::value> * = 0);
68
69         // Case 1
70         template <>
71         struct select<1> {
72             static bool const has_int_value = false;
73             void dazzle();
74         };
75         template <class T>
76         senf::mpl::rv<1> select_(...);
77
78         template <class T>
79         struct choice : public select<SENF_MPL_RV( select_<T>(0) )> {};
80
81         struct A { static const int value = 0; };
82         struct B {};
83
84         choice<A> a; a.frobble();
85         choice<B> b; b.dazzle();
86         \endcode
87
88         The selection is always based on two components: A selector class specialized for each of
89         the possible choices and an overloaded function (only signatures, no implementation needed)
90         to provide the conditions.
91
92         When instantiatinv <tt>choice<T></tt>, we forward \a T to the <tt>select_</tt> set of
93         overloads. Because of <a href="http://en.wikipedia.org/wiki/SFINAE">SFINAE</a>, the overload
94         set will only contain those instantiations, for which template expansion does not fail.
95
96         So, if \a T has an integer \c value member, both \c select_ overloads are ok and the call
97         <tt>select_<T>(0)</tt> will choose the first (case 0) variant, since the argument \c 0 is
98         better matched by \c int than by <tt>...</tt>.
99
100         However, if \a T does not have an integer \c value member, expansion for the first overload
101         fails and the overload set only contains the second case.
102
103         \ref SENF_MPL_RV() internally uses \c sizeof to find out, \e which overload was selected
104         and returns the senf::mpl::rv-argument of that overloads return type. For this to work, the
105         \c select_ functions need not be implemented since no code is generated and \c select_ is
106         never called.
107
108         This number is than forwarded as template argument to \c select which is specialized for
109         each case. Therefore, <tt>choice\<A\></tt> has a \c frobble() member whereas
110         <tt>choice\<B\></tt> has a \c dazzle() member.
111
112         \see \ref SENF_MPL_RV
113         \ingroup senfmpl
114      */
115     template <unsigned n>
116     struct rv {
117         char _[SENF_MPL_RV_ALIGNMENT][n+1];
118     };
119
120     /** \brief Get return value of overload selector
121
122         Used together with senf::mpl::rv to implement overload selection.
123
124         \see \ref senf::mpl::rv
125         \ingroup senfmpl
126         \hideinitializer
127      */
128 #   define SENF_MPL_RV(expr) (sizeof(expr)/SENF_MPL_RV_ALIGNMENT-1)
129
130     /** \brief Take an arbitrary unsigned integer template argument
131
132         Used together with <a href="http://en.wikipedia.org/wiki/SFINAE">SFINAE</a>: The expression
133         <tt>take_uint<</tt> \a expr <tt>></tt> is only valid if \a expr is valid and returns a value
134         convertible to an unsigned integer.
135
136         \ingroup senfmpl
137      */
138     template <unsigned long _> struct take_uint {};
139
140     /** \brief Take an arbitrary integer template argument
141
142         Used together with <a href="http://en.wikipedia.org/wiki/SFINAE">SFINAE</a>: The expression
143         <tt>take_int<</tt> \a expr <tt>></tt> is only valid if \a expr is valid and returns a value
144         convertible to an integer.
145
146         \ingroup senfmpl
147      */
148     template <long _> struct take_int {};
149
150     /** \brief Take an arbitrary type template argument
151
152         Used together with <a href="http://en.wikipedia.org/wiki/SFINAE">SFINAE</a>: The expression
153         <tt>take_class<</tt> \a expr <tt>></tt> is only valid if \a expr is valid and is a type.
154
155         \ingroup senfmpl
156      */
157     template <class _> struct take_class {};
158
159 #ifndef SENF_MPL_SLOT_NOEXPAND
160
161     /** \brief Define MPL slot
162
163         The slot macros \ref SENF_MPL_SLOT_DEF(), \ref SENF_MPL_SLOT_SET() and \ref
164         SENF_MPL_SLOT_GET() provide a facility to get the last unsigned integer value assigned to
165         the slot before the current point in the current class.
166         \code
167         struct Foo
168         {
169             // Define SLOT slot named 'accum' initialized to 0
170             SENF_MPL_SLOT_DEF(accum, 0);
171
172             // Add 2 to 'accum'
173             SENF_MPL_SLOT_SET(accum, SENF_MPL_SLOT_GET(accum) + 2);
174
175             // Multiply 'accum' by 3
176             SENF_MPL_SLOT_SET(accum, SENF_MPL_SLOT_GET(accum) * 3);
177
178             // Define the result as a constant expression. result is now 6
179             static unsigned result = SENF_MPL_SLOT_GET(accum);
180         };
181         \endcode
182         Of course, it does not make sense to use these macros for simple arithmetic as in the
183         example. The SENF_MPL_SLOT macros allow to define macros which pass information from one
184         macro invocation to the next.
185
186         \implementation The implementation is based on __LINE__: We check backwards for a value
187             defined on a previous line. The check is limited to 80 lines backwards.
188
189         \ingroup senfmpl
190         \hideinitializer
191      */
192 #   define SENF_MPL_SLOT_DEF(name,value)                                                          \
193         template <class _>                                                                        \
194         static senf::mpl::rv<0> _SENF_MPL_SLOT_ ## name (_);                                      \
195         SENF_MPL_SLOT_SET(name,value)
196
197     /** \brief Define MPL slot initialized to 0
198
199         This is like \ref SENF_MPL_SLOT_DEF() but initializes the slot to the fixed value 0. The
200         advantage over \ref SENF_MPL_SLOT_DEF() is, that this macro may be called from an include
201         file whereas all the other \\c SENF_MPL_SLOT_ macros must always be called from the relevant
202         file.
203      */
204 #   define SENF_MPL_SLOT_DEF_ZERO(name)                                                           \
205         template <class _>                                                                        \
206         static senf::mpl::rv<0> _SENF_MPL_SLOT_ ## name (_);
207
208     /** \brief Set MPL slot
209         \see \ref SENF_MPL_SLOT_DEF()
210         \ingroup senfmpl
211         \hideinitializer
212      */
213 #   define SENF_MPL_SLOT_SET(name,value)                                                          \
214         static senf::mpl::rv<unsigned(value)+1>                                                   \
215             _SENF_MPL_SLOT_ ## name (senf::mpl::take_int<__LINE__>)
216
217     /** \brief Get current MPL slot value
218         \see \ref SENF_MPL_SLOT_DEF()
219         \ingroup senfmpl
220         \hideinitializer
221      */
222 #   define SENF_MPL_SLOT_GET(name)                                                                \
223         SENF_MPL_SLOT_I_GET(name)
224
225 #endif
226
227 }}
228
229 //-/////////////////////////////////////////////////////////////////////////////////////////////////
230 //#include "mpl.cci"
231 //#include "mpl.ct"
232 //#include "mpl.cti"
233 #endif
234
235 \f
236 // Local Variables:
237 // mode: c++
238 // fill-column: 100
239 // comment-column: 40
240 // c-file-style: "senf"
241 // indent-tabs-mode: nil
242 // ispell-local-dictionary: "american"
243 // compile-command: "scons -u test"
244 // End: