Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: downloads/boost_1_33_1/libs/utility/enable_if.html @ 14

Last change on this file since 14 was 12, checked in by landauf, 17 years ago

added boost

File size: 16.4 KB
Line 
1<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"
2            "http://www.w3.org/TR/REC-html40/loose.dtd">
3<HTML>
4<HEAD><TITLE>enable_if</TITLE>
5
6<META http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
7<META name="GENERATOR" content="Microsoft FrontPage 5.0">
8</HEAD>
9<BODY >
10<!--HEVEA command line is: hevea -nosymb -noiso -pedantic -v enable_if_docs_for_boost.tex -->
11<!--HTMLHEAD-->
12<!--ENDHTML-->
13<!--PREFIX <ARG ></ARG>-->
14<!--CUT DEF section 1 -->
15<BR>
16<BR>
17
18
19<h1>
20<img border="0" src="../../boost.png" align="center" width="277" height="86">enable_if</h1>
21<BR>
22<BR>
23Copyright 2003 Jaakko J&auml;rvi, Jeremiah Willcock, Andrew Lumsdaine.<BR>
24<BR>
25<!--TOC section Introduction-->
26
27<H2><A NAME="htoc1">1</A>&nbsp;&nbsp;Introduction</H2><!--SEC END -->
28
29<A NAME="introduction"></A>
30The <TT>enable_if</TT> family of templates is a set of tools to allow a function template or a class template specialization
31to include or exclude itself from a set of matching functions or specializations
32based on properties of its template arguments.
33For example, one can define function templates that
34are only enabled for, and thus only match, an arbitrary set of types
35defined by a traits class. The <TT>enable_if</TT> templates can also be
36applied to enable class template specializations. Applications of
37<TT>enable_if</TT> are discussed in length
38in&nbsp;[<A HREF="#jarvi:03:cuj_arbitrary_overloading"><CITE>1</CITE></A>] and&nbsp;[<A HREF="#jarvi:03:c++typeclasses"><CITE>2</CITE></A>].<BR>
39<BR>
40<!--TOC subsection Synopsis-->
41
42<H3><A NAME="htoc2">1.1</A>&nbsp;&nbsp;Synopsis</H3><!--SEC END -->
43
44<A NAME="sec:synopsis"></A>
45<PRE>namespace boost {
46  template &lt;class Cond, class T = void&gt; struct enable_if;
47  template &lt;class Cond, class T = void&gt; struct disable_if;
48  template &lt;class Cond, class T&gt; struct lazy_enable_if;
49  template &lt;class Cond, class T&gt; struct lazy_disable_if;
50
51  template &lt;bool B, class T = void&gt; struct enable_if_c;
52  template &lt;bool B, class T = void&gt; struct disable_if_c;
53  template &lt;bool B, class T&gt; struct lazy_enable_if_c;
54  template &lt;bool B, class T&gt; struct lazy_disable_if_c;
55}
56</PRE>
57<!--TOC subsection Background-->
58
59<H3><A NAME="htoc3">1.2</A>&nbsp;&nbsp;Background</H3><!--SEC END -->
60
61<A NAME="sec:background"></A>
62Sensible operation of template function overloading in C++ relies
63on the <EM>SFINAE</EM> (substitution-failure-is-not-an-error)
64principle&nbsp;[<A HREF="#vandevoorde2002:templates"><CITE>3</CITE></A>]: if an invalid argument
65or return type is formed during the instantiation of a function
66template, the instantiation is removed from the overload resolution
67set instead of causing a compilation error. The following example,
68taken from&nbsp;[<A HREF="#jarvi:03:cuj_arbitrary_overloading"><CITE>1</CITE></A>],
69demonstrates why this is important:
70<PRE>int negate(int i) { return -i; }
71
72template &lt;class F&gt;
73typename F::result_type negate(const F&amp; f) { return -f(); }
74
75</PRE>
76Suppose the compiler encounters the call <TT>negate(1)</TT>. The first
77definition is obviously a better match, but the compiler must
78nevertheless consider (and instantiate the prototypes) of both
79definitions to find this out. Instantiating the latter definition with
80<TT>F</TT> as <TT>int</TT> would result in:
81<PRE>int::result_type negate(const int&amp;);
82
83</PRE>
84where the return type is invalid. If this was an error, adding an unrelated function template
85(that was never called) could break otherwise valid code.
86Due to the SFINAE principle the above example is not, however, erroneous.
87The latter definition of <TT>negate</TT> is simply removed from the overload resolution set.<BR>
88<BR>
89The <TT>enable_if</TT> templates are tools for controlled creation of the SFINAE
90conditions.<BR>
91<BR>
92<!--TOC section The <TT>enable_if</TT> templates-->
93
94<H2><A NAME="htoc4">2</A>&nbsp;&nbsp;The <TT>enable_if</TT> templates</H2><!--SEC END -->
95
96<A NAME="enable_if"></A>
97The names of the <TT>enable_if</TT> templates have three parts: an optional <TT>lazy_</TT> tag,
98either <TT>enable_if</TT> or <TT>disable_if</TT>, and an optional <TT>_c</TT> tag.
99All eight combinations of these parts are supported.
100The meaning of the <TT>lazy_</TT> tag is described in Section&nbsp;<A HREF="#sec:enable_if_lazy">3.3</A>.
101The second part of the name indicates whether a true condition argument should
102enable or disable the current overload.
103The third part of the name indicates whether the condition argument is a <TT>bool</TT> value
104(<TT>_c</TT> suffix), or a type containing a static <TT>bool</TT> constant named <TT>value</TT> (no suffix).
105The latter version interoperates with Boost.MPL. <BR>
106<BR>
107The definitions of <TT>enable_if_c</TT> and <TT>enable_if</TT> are as follows (we use <TT>enable_if</TT> templates
108unqualified but they are in the <TT>boost</TT> namespace).
109<PRE>template &lt;bool B, class T = void&gt;
110struct enable_if_c {
111  typedef T type;
112};
113
114template &lt;class T&gt;
115struct enable_if_c&lt;false, T&gt; {};
116
117template &lt;class Cond, class T = void&gt;
118struct enable_if : public enable_if_c&lt;Cond::value, T&gt; {};
119
120</PRE>
121An instantiation of the <TT>enable_if_c</TT> template with the parameter
122<TT>B</TT> as <TT>true</TT> contains a member type <TT>type</TT>, defined
123to be <TT>T</TT>. If <TT>B</TT> is
124<TT>false</TT>, no such member is defined. Thus
125<TT>enable_if_c&lt;B, T&gt;::type</TT> is either a valid or an invalid type
126expression, depending on the value of <TT>B</TT>.
127When valid, <TT>enable_if_c&lt;B, T&gt;::type</TT> equals <TT>T</TT>.
128The <TT>enable_if_c</TT> template can thus be used for controlling when functions are considered for
129overload resolution and when they are not.
130For example, the following function is defined for all arithmetic types (according to the
131classification of the <A HREF="../type_traits/index.html">Boost type_traits library</A>):
132<PRE>template &lt;class T&gt;
133typename enable_if_c&lt;boost::is_arithmetic&lt;T&gt;::value, T&gt;::type
134foo(T t) { return t; }
135
136</PRE>
137The <TT>disable_if_c</TT> template is provided as well, and has the
138same functionality as <TT>enable_if_c</TT> except for the negated condition. The following
139function is enabled for all non-arithmetic types.
140<PRE>template &lt;class T&gt;
141typename disable_if_c&lt;boost::is_arithmetic&lt;T&gt;::value, T&gt;::type
142bar(T t) { return t; }
143
144</PRE>
145For easier syntax in some cases and interoperation with Boost.MPL we provide versions of
146the <TT>enable_if</TT> templates taking any type with a <TT>bool</TT> member constant named
147<TT>value</TT> as the condition argument.
148The MPL <TT>bool_</TT>, <TT>and_</TT>, <TT>or_</TT>, and <TT>not_</TT> templates are likely to be
149useful for creating such types. Also, the traits classes in the Boost.Type_traits library
150follow this convention.
151For example, the above example function <TT>foo</TT> can be alternatively written as:
152<PRE>template &lt;class T&gt;
153typename enable_if&lt;boost::is_arithmetic&lt;T&gt;, T&gt;::type
154foo(T t) { return t; }
155
156</PRE>
157<!--TOC section Using <TT>enable_if</TT>-->
158
159<H2><A NAME="htoc5">3</A>&nbsp;&nbsp;Using <TT>enable_if</TT></H2><!--SEC END -->
160
161<A NAME="sec:using_enable_if"></A>
162The <TT>enable_if</TT> templates are defined in
163<TT>boost/utility/enable_if.hpp</TT>, which is included by <TT>boost/utility.hpp</TT>.<BR>
164<BR>
165The <TT>enable_if</TT> template can be used either as the return type, or as an
166extra argument. For example, the <TT>foo</TT> function in the previous section could also be written
167as:
168<PRE>template &lt;class T&gt;
169T foo(T t, typename enable_if&lt;boost::is_arithmetic&lt;T&gt; &gt;::type* dummy = 0);
170
171</PRE>Hence, an extra parameter of type <TT>void*</TT> is added, but it is given
172a default value to keep the parameter hidden from client code.
173Note that the second template argument was not given to <TT>enable_if</TT>, as the default
174<TT>void</TT> gives the desired behavior.<BR>
175<BR>
176Whether to write the enabler as an argument or within the return type is
177largely a matter of taste, but for certain functions, only one
178alternative is possible:
179<UL><LI>
180Operators have a fixed number of arguments, thus <TT>enable_if</TT> must be used in the return type.
181<LI>Constructors and destructors do not have a return type; an extra argument is the only option.
182<LI>There does not seem to be a way to specify an enabler for a conversion operator. Converting constructors,
183however, can have enablers as extra default arguments.
184</UL>
185<!--TOC subsection Enabling template class specializations-->
186
187<H3><A NAME="htoc6">3.1</A>&nbsp;&nbsp;Enabling template class specializations</H3><!--SEC END -->
188
189<A NAME="sec:enable_if_classes"></A>
190Class template specializations can be enabled or disabled with <TT>enable_if</TT>.
191One extra template parameter needs to be added for the enabler expressions.
192This parameter has the default value <TT>void</TT>.
193For example:
194<PRE>template &lt;class T, class Enable = void&gt; 
195class A { ... };
196
197template &lt;class T&gt;
198class A&lt;T, typename enable_if&lt;is_integral&lt;T&gt; &gt;::type&gt; { ... };
199
200template &lt;class T&gt;
201class A&lt;T, typename enable_if&lt;is_float&lt;T&gt; &gt;::type&gt; { ... };
202
203</PRE>Instantiating <TT>A</TT> with any integral type matches the first specialization,
204whereas any floating point type matches the second one. All other types
205match the primary template.
206The condition can be any compile-time boolean expression that depends on the
207template arguments of the class.
208Note that again, the second argument to <TT>enable_if</TT> is not needed; the default (<TT>void</TT>)
209is the correct value.<BR>
210<BR>
211<!--TOC subsection Overlapping enabler conditions-->
212
213<H3><A NAME="htoc7">3.2</A>&nbsp;&nbsp;Overlapping enabler conditions</H3><!--SEC END -->
214
215<A NAME="sec:overlapping_conditions"></A>
216Once the compiler has examined the enabling conditions and included the
217function into the overload resolution set, normal C++ overload resolution
218rules are used to select the best matching function.
219In particular, there is no ordering between enabling conditions.
220Function templates with enabling conditions that are not mutually exclusive can
221lead to ambiguities. For example:
222<PRE>template &lt;class T&gt;
223typename enable_if&lt;boost::is_integral&lt;T&gt;, void&gt;::type
224foo(T t) {}
225
226template &lt;class T&gt;
227typename enable_if&lt;boost::is_arithmetic&lt;T&gt;, void&gt;::type
228foo(T t) {}
229
230</PRE>
231All integral types are also arithmetic. Therefore, say, for the call <TT>foo(1)</TT>,
232both conditions are true and both functions are thus in the overload resolution set.
233They are both equally good matches and thus ambiguous.
234Of course, more than one enabling condition can be simultaneously true as long as
235other arguments disambiguate the functions.<BR>
236<BR>
237The above discussion applies to using <TT>enable_if</TT> in class template
238partial specializations as well.<BR>
239<BR>
240<!--TOC subsection Lazy <TT>enable_if</TT>-->
241
242<H3><A NAME="htoc8">3.3</A>&nbsp;&nbsp;Lazy <TT>enable_if</TT></H3><!--SEC END -->
243
244<A NAME="sec:enable_if_lazy"></A>
245In some cases it is necessary to avoid instantiating part of a
246function signature unless an enabling condition is true. For example:
247<PRE>template &lt;class T, class U&gt; class mult_traits;
248
249template &lt;class T, class U&gt;
250typename enable_if&lt;is_multipliable&lt;T, U&gt;, typename mult_traits&lt;T, U&gt;::type&gt;::type
251operator*(const T&amp; t, const U&amp; u) { ... }
252
253</PRE>Assume the class template <TT>mult_traits</TT> is a traits class defining
254the resulting type of a multiplication operator. The <TT>is_multipliable</TT> traits
255class specifies for which types to enable the operator. Whenever
256<TT>is_multipliable&lt;A, B&gt;::value</TT> is <TT>true</TT> for some types <TT>A</TT> and <TT>B</TT>,
257then <TT>mult_traits&lt;A, B&gt;::type</TT> is defined.<BR>
258<BR>
259Now, trying to invoke (some other overload) of <TT>operator*</TT> with, say, operand types <TT>C</TT> and <TT>D</TT> 
260for which <TT>is_multipliable&lt;C, D&gt;::value</TT> is <TT>false</TT> 
261and <TT>mult_traits&lt;C, D&gt;::type</TT> is not defined is an error on some compilers.
262The SFINAE principle is not applied because
263the invalid type occurs as an argument to another template. The <TT>lazy_enable_if</TT> 
264and <TT>lazy_disable_if</TT> templates (and their <TT>_c</TT> versions) can be used in such
265situations:
266<PRE>template&lt;class T, class U&gt;
267typename lazy_enable_if&lt;is_multipliable&lt;T, U&gt;, mult_traits&lt;T, U&gt; &gt;::type
268operator*(const T&amp; t, const U&amp; u) { ... }
269
270</PRE>The second argument of <TT>lazy_enable_if</TT> must be a class type
271that defines a nested type named <TT>type</TT> whenever the first
272parameter (the condition) is true.<BR>
273<BR>
274<!--TOC paragraph Note-->
275
276<H5>Note</H5><!--SEC END -->
277
278Referring to one member type or static constant in a traits class
279causes all of the members (type and static constant) of that
280specialization to be instantiated. Therefore, if your traits classes
281can sometimes contain invalid types, you should use two distinct
282templates for describing the conditions and the type mappings. In the
283above example, <TT>is_multipliable&lt;T, U&gt;::value</TT> defines when
284<TT>mult_traits&lt;T, U&gt;::type</TT> is valid.<BR>
285<BR>
286<!--TOC subsection Compiler workarounds-->
287
288<H3><A NAME="htoc9">3.4</A>&nbsp;&nbsp;Compiler workarounds</H3><!--SEC END -->
289
290<A NAME="sec:workarounds"></A>
291Some compilers flag functions as ambiguous if the only distinguishing factor is a different
292condition in an enabler (even though the functions could never be ambiguous). For example,
293some compilers (e.g. GCC 3.2) diagnose the following two functions as ambiguous:
294<PRE>template &lt;class T&gt;
295typename enable_if&lt;boost::is_arithmetic&lt;T&gt;, T&gt;::type
296foo(T t);
297
298template &lt;class T&gt;
299typename disable_if&lt;boost::is_arithmetic&lt;T&gt;, T&gt;::type
300foo(T t);
301
302</PRE>Two workarounds can be applied:
303<UL><LI>
304Use an extra dummy parameter which disambiguates the functions. Use a default value for
305it to hide the parameter from the caller. For example:
306<PRE>template &lt;int&gt; struct dummy { dummy(int) {} };
307
308template &lt;class T&gt;
309typename enable_if&lt;boost::is_arithmetic&lt;T&gt;, T&gt;::type
310foo(T t, dummy&lt;0&gt; = 0);
311
312template &lt;class T&gt;
313typename disable_if&lt;boost::is_arithmetic&lt;T&gt;, T&gt;::type
314foo(T t, dummy&lt;1&gt; = 0);
315</PRE><BR>
316<BR>
317<LI>Define the functions in different namespaces and bring them into a common
318namespace with <TT>using</TT> declarations:
319<PRE>namespace A {
320  template &lt;class T&gt;
321  typename enable_if&lt;boost::is_arithmetic&lt;T&gt;, T&gt;::type
322  foo(T t);
323}
324
325namespace B {
326  template &lt;class T&gt;
327  typename disable_if&lt;boost::is_arithmetic&lt;T&gt;, T&gt;::type
328  foo(T t);
329}
330
331using A::foo;
332using B::foo;
333
334</PRE>
335Note that the second workaround above cannot be used for member
336templates. On the other hand, operators do not accept extra arguments,
337which makes the first workaround unusable. As the net effect,
338neither of the workarounds are of assistance for templated operators that
339need to be defined as member functions (assignment and
340subscript operators).
341</UL>
342<!--TOC section Acknowledgements-->
343
344<H2><A NAME="htoc10">4</A>&nbsp;&nbsp;Acknowledgements</H2><!--SEC END -->
345
346We are grateful to Howard Hinnant, Jason Shirk, Paul Mensonides, and Richard
347Smith whose findings have influenced the library.<BR>
348<BR>
349<!--TOC section References-->
350
351<H2>References</H2><!--SEC END -->
352<DL COMPACT=compact><DT><A NAME="jarvi:03:cuj_arbitrary_overloading"><FONT COLOR=purple>[1]</FONT></A><DD>
353Jaakko J&auml;rvi, Jeremiah Willcock, Howard Hinnant, and Andrew Lumsdaine.
354Function overloading based on arbitrary properties of types.
355<EM>C/C++ Users Journal</EM>, 21(6):25--32, June 2003.<BR>
356<BR>
357<DT><A NAME="jarvi:03:c++typeclasses"><FONT COLOR=purple>[2]</FONT></A><DD>
358Jaakko J&auml;rvi, Jeremiah Willcock, and Andrew Lumsdaine.
359Concept-controlled polymorphism.
360In Frank Pfennig and Yannis Smaragdakis, editors, <EM>Generative
361 Programming and Component Engineering</EM>, volume 2830 of <EM>LNCS</EM>, pages
362 228--244. Springer Verlag, September 2003.<BR>
363<BR>
364<DT><A NAME="vandevoorde2002:templates"><FONT COLOR=purple>[3]</FONT></A><DD>
365David Vandevoorde and Nicolai&nbsp;M. Josuttis.
366<EM>C++ Templates: The Complete Guide</EM>.
367Addison-Wesley, 2002.</DL>
368
369
370
371
372
373<hr></hr>
374
375<B>Contributed by:</B> <BR>
376Jaakko J&auml;rvi, Jeremiah Willcock and Andrew Lumsdaine<BR>
377<EM>{jajarvi|jewillco|lums}@osl.iu.edu</EM><BR>
378Indiana University<BR>
379Open Systems Lab
380<!--HTMLFOOT-->
381<!--ENDHTML-->
382<!--FOOTER-->
383<HR SIZE=2>
384<BLOCKQUOTE><EM>This document was translated from L<sup>A</sup>T<sub>E</sub>X by
385</EM><A HREF="http://pauillac.inria.fr/~maranget/hevea/index.html"><EM>H<FONT SIZE=2><sup>E</sup></FONT>V<FONT SIZE=2><sup>E</sup></FONT>A</EM></A><EM>.
386</EM></BLOCKQUOTE>
387</BODY>
388</HTML>
Note: See TracBrowser for help on using the repository browser.