4 // Fraunhofer Institute for Open Communication Systems (FOKUS)
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
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.
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.
19 // The Original Code is Fraunhofer FOKUS code.
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.
26 // Stefan Bund <g0dil@berlios.de>
29 \brief mpl public header */
31 #ifndef HH_SENF_Utils_mpl_
32 #define HH_SENF_Utils_mpl_ 1
35 #include <senf/config.hh>
39 //-/////////////////////////////////////////////////////////////////////////////////////////////////
44 /** \defgroup senfmpl Template meta programming helpers
47 /** \brief Marker class for empty default values etc.
49 This is like Boosts \c boost::mpl::na just an empty class used as template default argument
50 to mark missing arguments
52 \note Don't use this as an empty base class. We may add some informative members to this.
57 /** \brief Return-value type used to implement overload selection
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:
63 template <unsigned _> struct select {};
68 static bool const has_int_value = true;
72 senf::mpl::rv<0> select_(int, senf::mpl::take_int<T::value> * = 0);
77 static bool const has_int_value = false;
81 senf::mpl::rv<1> select_(...);
84 struct choice : public select<SENF_MPL_RV( select_<T>(0) )> {};
86 struct A { static const int value = 0; };
89 choice<A> a; a.frobble();
90 choice<B> b; b.dazzle();
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.
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.
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>.
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.
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
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.
117 \see \ref SENF_MPL_RV
120 template <unsigned n>
122 char _[SENF_MPL_RV_ALIGNMENT][n+1];
125 /** \brief Get return value of overload selector
127 Used together with senf::mpl::rv to implement overload selection.
129 \see \ref senf::mpl::rv
133 # define SENF_MPL_RV(expr) (sizeof(expr)/SENF_MPL_RV_ALIGNMENT-1)
135 /** \brief Take an arbitrary unsigned integer template argument
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.
143 template <unsigned long _> struct take_uint {};
145 /** \brief Take an arbitrary integer template argument
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.
153 template <long _> struct take_int {};
155 /** \brief Take an arbitrary type template argument
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.
162 template <class _> struct take_class {};
164 #ifndef SENF_MPL_SLOT_NOEXPAND
166 /** \brief Define MPL slot
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.
174 // Define SLOT slot named 'accum' initialized to 0
175 SENF_MPL_SLOT_DEF(accum, 0);
178 SENF_MPL_SLOT_SET(accum, SENF_MPL_SLOT_GET(accum) + 2);
180 // Multiply 'accum' by 3
181 SENF_MPL_SLOT_SET(accum, SENF_MPL_SLOT_GET(accum) * 3);
183 // Define the result as a constant expression. result is now 6
184 static unsigned result = SENF_MPL_SLOT_GET(accum);
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.
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.
197 # define SENF_MPL_SLOT_DEF(name,value) \
199 static senf::mpl::rv<0> _SENF_MPL_SLOT_ ## name (_); \
200 SENF_MPL_SLOT_SET(name,value)
202 /** \brief Define MPL slot initialized to 0
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
209 # define SENF_MPL_SLOT_DEF_ZERO(name) \
211 static senf::mpl::rv<0> _SENF_MPL_SLOT_ ## name (_);
213 /** \brief Set MPL slot
214 \see \ref SENF_MPL_SLOT_DEF()
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__>)
222 /** \brief Get current MPL slot value
223 \see \ref SENF_MPL_SLOT_DEF()
227 # define SENF_MPL_SLOT_GET(name) \
228 SENF_MPL_SLOT_I_GET(name)
234 //-/////////////////////////////////////////////////////////////////////////////////////////////////
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"