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