NEW FILE HEADER / COPYRIGHT FORMAT
[senf.git] / 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_mpl_
27 #define HH_mpl_ 1
28
29 // Custom includes
30 #include "../config.hh"
31
32 //#include "mpl.mpp"
33 #include "mpl.ih"
34 ///////////////////////////////hh.p////////////////////////////////////////
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      */
49     struct nil {};
50
51     /** \brief Return-value type used to implement overload selection
52
53         The senf::mpl::rv type is used together with \ref SENF_MPL_RV() to select template
54         specializations based on a set of overloads:
55
56         \code
57         template <unsigned _> struct select {};
58
59         // Case 0
60         template <>
61         struct select<0> {
62             static bool const has_int_value = true;
63             void frobble();
64         };
65         template <class T>
66         senf::mpl::rv<0> select_(int, senf::mpl::take_int<T::value> * = 0);
67
68         // Case 1
69         template <>
70         struct select<1> {
71             static bool const has_int_value = false;
72             void dazzle();
73         };
74         template <class T>
75         senf::mpl::rv<1> select_(...);
76
77         template <class T>
78         struct choice : public select<SENF_MPL_RV( select_<T>(0) )> {};
79
80         struct A { static const int value = 0; };
81         struct B {};
82
83         choice<A> a; a.frobble();
84         choice<B> b; b.dazzle();
85         \endcode
86
87         The selection is always based on two components: A selector class specialized for each of
88         the possible choices and an overloaded function (only signatures, no implementation needed)
89         to provide the conditions.
90
91         When instantiatinv <tt>choice<T></tt>, we forward \a T to the <tt>select_</tt> set of
92         overloads. Because of <a href="http://en.wikipedia.org/wiki/SFINAE">SFINAE</a>, the overload
93         set will only contain those instantiations, for which template expansion does not fail.
94
95         So, if \a T has an integer \c value member, both \c select_ overloads are ok and the call
96         <tt>select_<T>(0)</tt> will choose the first (case 0) variant, since the argument \c 0 is
97         better matched by \c int than by <tt>...</tt>.
98
99         However, if \a T does not have an integer \c value member, expansion for the first overload
100         fails and the overload set only contains the second case.
101
102         \ref SENF_MPL_RV() internally uses \c sizeof to find out, \e which overload was selected
103         and returns the senf::mpl::rv-argument of that overloads return type. For this to work, the
104         \c select_ functions need not be implemented since no code is generated and \c select_ is
105         never called.
106
107         This number is than forwarded as template argument to \c select which is specialized for
108         each case. Therefore, <tt>choice\<A\></tt> has a \c frobble() member whereas
109         <tt>choice\<B\></tt> has a \c dazzle() member.
110
111         \see \ref SENF_MPL_RV
112         \ingroup senfmpl
113      */
114     template <unsigned n>
115     struct rv { 
116         char _[SENF_MPL_RV_ALIGNMENT][n+1]; 
117     };
118
119     /** \brief Get return value of overload selector
120         
121         Used together with senf::mpl::rv to implement overload selection.
122         
123         \see \ref senf::mpl::rv
124         \ingroup senfmpl
125         \hideinitializer
126      */
127 #   define SENF_MPL_RV(expr) (sizeof(expr)/SENF_MPL_RV_ALIGNMENT-1)
128
129     /** \brief Take an arbitrary unsigned integer template argument
130         
131         Used together with <a href="http://en.wikipedia.org/wiki/SFINAE">SFINAE</a>: The expression
132         <tt>take_uint<</tt> \a expr <tt>></tt> is only valid if \a expr is valid and returns a value
133         convertible to an unsigned integer.
134
135         \ingroup senfmpl
136      */
137     template <unsigned long _> struct take_uint {};
138
139     /** \brief Take an arbitrary integer template argument
140         
141         Used together with <a href="http://en.wikipedia.org/wiki/SFINAE">SFINAE</a>: The expression
142         <tt>take_int<</tt> \a expr <tt>></tt> is only valid if \a expr is valid and returns a value
143         convertible to an integer.
144
145         \ingroup senfmpl
146      */
147     template <long _> struct take_int {};
148
149     /** \brief Take an arbitrary type template argument
150         
151         Used together with <a href="http://en.wikipedia.org/wiki/SFINAE">SFINAE</a>: The expression
152         <tt>take_class<</tt> \a expr <tt>></tt> is only valid if \a expr is valid and is a type.
153
154         \ingroup senfmpl
155      */
156     template <class _> struct take_class {};
157
158     /** \brief Define MPL slot
159
160         The slot macros \ref SENF_MPL_SLOT_DEF(), \ref SENF_MPL_SLOT_SET() and \ref
161         SENF_MPL_SLOT_GET() provide a facility to get the last unsigned integer value assigned to
162         the slot before the current point in the current class.
163         \code
164         struct Foo
165         {
166             // Define SLOT slot named 'accum' initialized to 0
167             SENF_MPL_SLOT_DEF(accum, 0);
168
169             // Add 2 to 'accum'
170             SENF_MPL_SLOT_SET(accum, SENF_MPL_SLOT_GET(accum) + 2);
171
172             // Multiply 'accum' by 3
173             SENF_MPL_SLOT_SET(accum, SENF_MPL_SLOT_GET(accum) * 3);
174
175             // Define the result as a constant expression. result is now 6
176             static unsigned result = SENF_MPL_SLOT_GET(accum);
177         };
178         \endcode
179         Of course, it does not make sense to use these macros for simple arithmetic as in the
180         example. The SENF_MPL_SLOT macros allow to define macros which pass information from one
181         macro invocation to the next.
182
183         \implementation The implementation is based on __LINE__: We check backwards for a value
184             defined on a previous line. The check is limited to 80 lines backwards.
185
186         \ingroup senfmpl
187         \hideinitializer
188      */
189 #   define SENF_MPL_SLOT_DEF(name,value)                                                          \
190         template <class _>                                                                        \
191         static senf::mpl::rv<0> _SENF_MPL_SLOT_ ## name (_);                                      \
192         SENF_MPL_SLOT_SET(name,value)
193
194     /** \brief Define MPL slot initialized to 0
195
196         This is like \ref SENF_MPL_SLOT_DEF() but initializes the slot to the fixed value 0. The
197         advantage over \ref SENF_MPL_SLOT_DEF() is, that this macro may be called from an include
198         file whereas all the other \\c SENF_MPL_SLOT_ macros must always be called from the relevant
199         file.
200      */
201 #   define SENF_MPL_SLOT_DEF_ZERO(name)                                                           \
202         template <class _>                                                                        \
203         static senf::mpl::rv<0> _SENF_MPL_SLOT_ ## name (_);
204
205     /** \brief Set MPL slot
206         \see \ref SENF_MPL_SLOT_DEF()
207         \ingroup senfmpl
208         \hideinitializer
209      */
210 #   define SENF_MPL_SLOT_SET(name,value)                                                          \
211         static senf::mpl::rv<unsigned(value)+1>                                                   \
212             _SENF_MPL_SLOT_ ## name (senf::mpl::take_int<__LINE__>)
213
214     /** \brief Get current MPL slot value
215         \see \ref SENF_MPL_SLOT_DEF()
216         \ingroup senfmpl
217         \hideinitializer
218      */
219 #   define SENF_MPL_SLOT_GET(name)                                                                \
220         SENF_MPL_SLOT_I_GET(name)
221
222 }}
223
224 ///////////////////////////////hh.e////////////////////////////////////////
225 //#include "mpl.cci"
226 //#include "mpl.ct"
227 //#include "mpl.cti"
228 #endif
229
230 \f
231 // Local Variables:
232 // mode: c++
233 // fill-column: 100
234 // comment-column: 40
235 // c-file-style: "senf"
236 // indent-tabs-mode: nil
237 // ispell-local-dictionary: "american"
238 // compile-command: "scons -u test"
239 // End: