4 // Fraunhofer Institute for Open Communication Systems (FOKUS)
5 // Competence Center NETwork research (NET), St. Augustin, GERMANY
6 // Stefan Bund <g0dil@berlios.de>
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.
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.
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.
24 \brief mpl public header */
26 #ifndef HH_SENF_Utils_mpl_
27 #define HH_SENF_Utils_mpl_ 1
30 #include "../config.hh"
34 ///////////////////////////////hh.p////////////////////////////////////////
39 /** \defgroup senfmpl Template meta programming helpers
42 /** \brief Marker class for empty default values etc.
44 This is like Boosts \c boost::mpl::na just an empty class used as template default argument
45 to mark missing arguments
47 \note Don't use this as an empty base class. We may add some informative members to this.
52 /** \brief Return-value type used to implement overload selection
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:
58 template <unsigned _> struct select {};
63 static bool const has_int_value = true;
67 senf::mpl::rv<0> select_(int, senf::mpl::take_int<T::value> * = 0);
72 static bool const has_int_value = false;
76 senf::mpl::rv<1> select_(...);
79 struct choice : public select<SENF_MPL_RV( select_<T>(0) )> {};
81 struct A { static const int value = 0; };
84 choice<A> a; a.frobble();
85 choice<B> b; b.dazzle();
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.
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.
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>.
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.
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
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.
112 \see \ref SENF_MPL_RV
115 template <unsigned n>
117 char _[SENF_MPL_RV_ALIGNMENT][n+1];
120 /** \brief Get return value of overload selector
122 Used together with senf::mpl::rv to implement overload selection.
124 \see \ref senf::mpl::rv
128 # define SENF_MPL_RV(expr) (sizeof(expr)/SENF_MPL_RV_ALIGNMENT-1)
130 /** \brief Take an arbitrary unsigned integer template argument
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.
138 template <unsigned long _> struct take_uint {};
140 /** \brief Take an arbitrary integer template argument
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.
148 template <long _> struct take_int {};
150 /** \brief Take an arbitrary type template argument
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.
157 template <class _> struct take_class {};
159 #ifndef SENF_MPL_SLOT_NOEXPAND
161 /** \brief Define MPL slot
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.
169 // Define SLOT slot named 'accum' initialized to 0
170 SENF_MPL_SLOT_DEF(accum, 0);
173 SENF_MPL_SLOT_SET(accum, SENF_MPL_SLOT_GET(accum) + 2);
175 // Multiply 'accum' by 3
176 SENF_MPL_SLOT_SET(accum, SENF_MPL_SLOT_GET(accum) * 3);
178 // Define the result as a constant expression. result is now 6
179 static unsigned result = SENF_MPL_SLOT_GET(accum);
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.
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.
192 # define SENF_MPL_SLOT_DEF(name,value) \
194 static senf::mpl::rv<0> _SENF_MPL_SLOT_ ## name (_); \
195 SENF_MPL_SLOT_SET(name,value)
197 /** \brief Define MPL slot initialized to 0
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
204 # define SENF_MPL_SLOT_DEF_ZERO(name) \
206 static senf::mpl::rv<0> _SENF_MPL_SLOT_ ## name (_);
208 /** \brief Set MPL slot
209 \see \ref SENF_MPL_SLOT_DEF()
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__>)
217 /** \brief Get current MPL slot value
218 \see \ref SENF_MPL_SLOT_DEF()
222 # define SENF_MPL_SLOT_GET(name) \
223 SENF_MPL_SLOT_I_GET(name)
229 ///////////////////////////////hh.e////////////////////////////////////////
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"