]> git.proxmox.com Git - ceph.git/blame - ceph/src/boost/libs/core/doc/enable_if.qbk
bump version to 12.2.2-pve1
[ceph.git] / ceph / src / boost / libs / core / doc / enable_if.qbk
CommitLineData
7c673cae
FG
1[/
2 / Copyright (c) 2003, 2004 Jaakko Jarvi
3 / Copyright (c) 2008 John Maddock
4 / Copyright (c) 2011, 2013 Jeremiah Willcock
5 / Copyright (c) 2014 Glen Fernandes
6 /
7 / Use, modification, and distribution is subject to the Boost Software
8 / License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
9 / http://www.boost.org/LICENSE_1_0.txt)
10 /]
11
12[section:enable_if enable_if]
13
14[simplesect Authors]
15
16* Jaakko J\u00E4rvi
17* Jeremiah Willcock
18* Andrew Lumsdaine
19
20[endsimplesect]
21
22[section Introduction]
23
24The `enable_if` family of templates is a set of tools to allow
25a function template or a class template specialization to
26include or exclude itself from a set of matching functions or
27specializations based on properties of its template arguments.
28For example, one can define function templates that are only
29enabled for, and thus only match, an arbitrary set of types
30defined by a traits class. The `enable_if` templates can also
31be applied to enable class template specializations.
32Applications of `enable_if` are discussed in length in
33[link REF1 \[1\]] and [link REF2 \[2\]].
34
35[section Header <boost/core/enable_if.hpp>]
36
37``
38namespace boost {
39 template <class Cond, class T = void> struct enable_if;
40 template <class Cond, class T = void> struct disable_if;
41 template <class Cond, class T> struct lazy_enable_if;
42 template <class Cond, class T> struct lazy_disable_if;
43
44 template <bool B, class T = void> struct enable_if_c;
45 template <bool B, class T = void> struct disable_if_c;
46 template <bool B, class T> struct lazy_enable_if_c;
47 template <bool B, class T> struct lazy_disable_if_c;
48}
49``
50
51[endsect]
52
53[section Background]
54
55Sensible operation of template function overloading in C++
56relies on the /SFINAE/ (substitution-failure-is-not-an-error)
57principle [link REF3 \[3\]]: if an invalid argument or return
58type is formed during the instantiation of a function template,
59the instantiation is removed from the overload resolution set
60instead of causing a compilation error. The following example,
61taken from [link REF1 \[1\]], demonstrates why this is
62important:
63
64``
65int negate(int i) { return -i; }
66
67template <class F>
68typename F::result_type negate(const F& f) { return -f(); }
69``
70
71Suppose the compiler encounters the call `negate(1)`. The first
72definition is obviously a better match, but the compiler must
73nevertheless consider (and instantiate the prototypes) of both
74definitions to find this out. Instantiating the latter
75definition with `F` as `int` would result in:
76
77``
78int::result_type negate(const int&);
79``
80
81where the return type is invalid. If this were an error, adding
82an unrelated function template (that was never called) could
83break otherwise valid code. Due to the SFINAE principle the
84above example is not, however, erroneous. The latter definition
85of `negate` is simply removed from the overload resolution set.
86
87The `enable_if` templates are tools for controlled creation of
88the SFINAE conditions.
89
90[endsect]
91
92[endsect]
93
94[section The enable_if templates]
95
96The names of the `enable_if` templates have three parts: an
97optional `lazy_` tag, either `enable_if` or `disable_if`, and
98an optional `_c` tag. All eight combinations of these parts
99are supported. The meaning of the `lazy_` tag is described
100in the section [link
101core.enable_if.using_enable_if.enable_if_lazy below]. The
102second part of the name indicates whether a true condition
103argument should enable or disable the current overload. The
104third part of the name indicates whether the condition
105argument is a `bool` value (`_c` suffix), or a type containing
106a static `bool` constant named `value` (no suffix). The latter
107version interoperates with Boost.MPL.
108
109The definitions of `enable_if_c` and `enable_if` are as follows
110(we use `enable_if` templates unqualified but they are in the
111`boost` namespace).
112
113``
114template <bool B, class T = void>
115struct enable_if_c {
116 typedef T type;
117};
118
119template <class T>
120struct enable_if_c<false, T> {};
121
122template <class Cond, class T = void>
123struct enable_if : public enable_if_c<Cond::value, T> {};
124``
125
126An instantiation of the `enable_if_c` template with the
127parameter `B` as `true` contains a member type `type`, defined
128to be `T`. If `B` is `false`, no such member is defined. Thus
129`enable_if_c<B, T>::type` is either a valid or an invalid type
130expression, depending on the value of `B`. When valid,
131`enable_if_c<B, T>::type` equals `T`. The `enable_if_c`
132template can thus be used for controlling when functions are
133considered for overload resolution and when they are not. For
134example, the following function is defined for all arithmetic
135types (according to the classification of the Boost
136*type_traits* library):
137
138``
139template <class T>
140typename enable_if_c<boost::is_arithmetic<T>::value, T>::type
141foo(T t) { return t; }
142``
143
144The `disable_if_c` template is provided as well, and has the
145same functionality as `enable_if_c` except for the negated
146condition. The following function is enabled for all
147non-arithmetic types.
148
149``
150template <class T>
151typename disable_if_c<boost::is_arithmetic<T>::value, T>::type
152bar(T t) { return t; }
153``
154
155For easier syntax in some cases and interoperation with
156Boost.MPL we provide versions of the `enable_if` templates
157taking any type with a `bool` member constant named `value` as
158the condition argument. The MPL `bool_`, `and_`, `or_`, and
159`not_` templates are likely to be useful for creating such
160types. Also, the traits classes in the Boost.Type_traits
161library follow this convention. For example, the above example
162function `foo` can be alternatively written as:
163
164``
165template <class T>
166typename enable_if<boost::is_arithmetic<T>, T>::type
167foo(T t) { return t; }
168``
169
170[endsect]
171
172[section:using_enable_if Using enable_if]
173
174The `enable_if` templates are defined in
175`boost/utility/enable_if.hpp`, which is included by
176`boost/utility.hpp`.
177
178With respect to function templates, `enable_if` can be used in
179multiple different ways:
180
181* As the return type of an instantiatied function
182* As an extra parameter of an instantiated function
183* As an extra template parameter (useful only in a compiler
184 that supports C++0x default arguments for function template
185 parameters, see [link
186 core.enable_if.using_enable_if.enable_if_0x Enabling function
187 templates in C++0x] for details.
188
189In the previous section, the return type form of `enable_if`
190was shown. As an example of using the form of `enable_if` that
191works via an extra function parameter, the `foo` function in
192the previous section could also be written as:
193
194``
195template <class T>
196T foo(T t,
197 typename enable_if<boost::is_arithmetic<T> >::type* dummy = 0);
198``
199
200Hence, an extra parameter of type `void*` is added, but it is
201given a default value to keep the parameter hidden from client
202code. Note that the second template argument was not given to
203`enable_if`, as the default `void` gives the desired behavior.
204
205Which way to write the enabler is largely a matter of taste,
206but for certain functions, only a subset of the options is
207possible:
208
209* Many operators have a fixed number of arguments, thus
210 `enable_if` must be used either in the return type or in an
211 extra template parameter.
212* Functions that have a variadic parameter list must use either
213 the return type form or an extra template parameter.
214* Constructors do not have a return type so you must use either
215 an extra function parameter or an extra template parameter.
216* Constructors that have a variadic parameter list must an
217 extra template parameter.
218* Conversion operators can only be written with an extra
219 template parameter.
220
221[section:enable_if_0x Enabling function templates in C++0x]
222
223In a compiler which supports C++0x default arguments for
224function template parameters, you can enable and disable
225function templates by adding an additional template parameter.
226This approach works in all situations where you would use
227either the return type form of `enable_if` or the function
228parameter form, including operators, constructors, variadic
229function templates, and even overloaded conversion operations.
230
231As an example:
232
233``
234#include <boost/type_traits/is_arithmetic.hpp>
235#include <boost/type_traits/is_pointer.hpp>
236#include <boost/utility/enable_if.hpp>
237
238class test
239{
240public:
241 // A constructor that works for any argument list of size 10
242 template< class... T,
243 typename boost::enable_if_c< sizeof...( T ) == 10,
244 int >::type = 0>
245 test( T&&... );
246
247 // A conversion operation that can convert to any arithmetic type
248 template< class T,
249 typename boost::enable_if< boost::is_arithmetic< T >,
250 int >::type = 0>
251 operator T() const;
252
253 // A conversion operation that can convert to any pointer type
254 template< class T,
255 typename boost::enable_if< boost::is_pointer< T >,
256 int >::type = 0>
257 operator T() const;
258};
259
260int main()
261{
262 // Works
263 test test_( 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 );
264
265 // Fails as expected
266 test fail_construction( 1, 2, 3, 4, 5 );
267
268 // Works by calling the conversion operator enabled for arithmetic types
269 int arithmetic_object = test_;
270
271 // Works by calling the conversion operator enabled for pointer types
272 int* pointer_object = test_;
273
274 // Fails as expected
275 struct {} fail_conversion = test_;
276}
277``
278
279[endsect]
280
281[section Enabling template class specializations]
282
283Class template specializations can be enabled or disabled with
284`enable_if`. One extra template parameter needs to be added for
285the enabler expressions. This parameter has the default value
286`void`. For example:
287
288``
289template <class T, class Enable = void>
290class A { ... };
291
292template <class T>
293class A<T, typename enable_if<is_integral<T> >::type> { ... };
294
295template <class T>
296class A<T, typename enable_if<is_float<T> >::type> { ... };
297``
298
299Instantiating `A` with any integral type matches the first
300specialization, whereas any floating point type matches the
301second one. All other types match the primary template.
302The condition can be any compile-time boolean expression that
303depends on the template arguments of the class. Note that
304again, the second argument to `enable_if` is not needed; the
305default (`void`) is the correct value.
306
307The `enable_if_has_type` template is usable this scenario but instead of
308using a type traits to enable or disable a specialization, it use a
309SFINAE context to check for the existence of a dependent type inside
310its parameter. For example, the following structure extracts a dependent
311`value_type` from T if and only if `T::value_type` exists.
312
313``
314template <class T, class Enable = void>
315class value_type_from
316{
317 typedef T type;
318};
319
320template <class T>
321class value_type_from<T, typename enable_if_has_type<typename T::value_type>::type>
322{
323 typedef typename T::value_type type;
324};
325``
326
327[endsect]
328
329[section Overlapping enabler conditions]
330
331Once the compiler has examined the enabling conditions and
332included the function into the overload resolution set, normal
333C++ overload resolution rules are used to select the best
334matching function. In particular, there is no ordering between
335enabling conditions. Function templates with enabling
336conditions that are not mutually exclusive can lead to
337ambiguities. For example:
338
339``
340template <class T>
341typename enable_if<boost::is_integral<T>, void>::type
342foo(T t) {}
343
344template <class T>
345typename enable_if<boost::is_arithmetic<T>, void>::type
346foo(T t) {}
347``
348
349All integral types are also arithmetic. Therefore, say, for the
350call `foo(1)`, both conditions are true and both functions are
351thus in the overload resolution set. They are both equally good
352matches and thus ambiguous. Of course, more than one enabling
353condition can be simultaneously true as long as other arguments
354disambiguate the functions.
355
356The above discussion applies to using `enable_if` in class
357template partial specializations as well.
358
359[endsect]
360
361[section:enable_if_lazy Lazy enable_if]
362
363In some cases it is necessary to avoid instantiating part of a
364function signature unless an enabling condition is true. For
365example:
366
367``
368template <class T, class U> class mult_traits;
369
370template <class T, class U>
371typename enable_if<is_multipliable<T, U>,
372 typename mult_traits<T, U>::type>::type
373operator*(const T& t, const U& u) { ... }
374``
375
376Assume the class template `mult_traits` is a traits class
377defining the resulting type of a multiplication operator. The
378`is_multipliable` traits class specifies for which types to
379enable the operator. Whenever `is_multipliable<A, B>::value` is
380`true` for some types `A` and `B`, then
381`mult_traits<A, B>::type` is defined.
382
383Now, trying to invoke (some other overload) of `operator*`
384with, say, operand types `C` and `D` for which
385`is_multipliable<C, D>::value` is `false` and
386`mult_traits<C, D>::type` is not defined is an error on some
387compilers. The SFINAE principle is not applied because the
388invalid type occurs as an argument to another template. The
389`lazy_enable_if` and `lazy_disable_if` templates (and their
390`_c` versions) can be used in such situations:
391
392``
393template<class T, class U>
394typename lazy_enable_if<is_multipliable<T, U>,
395 mult_traits<T, U> >::type
396operator*(const T& t, const U& u) { ... }
397
398``The second argument of `lazy_enable_if` must be a class type
399that defines a nested type named `type` whenever the first
400parameter (the condition) is true.
401
402[note Referring to one member type or static constant in a
403traits class causes all of the members (type and static
404constant) of that specialization to be instantiated.
405Therefore, if your traits classes can sometimes contain invalid
406types, you should use two distinct templates for describing the
407conditions and the type mappings. In the above example,
408`is_multipliable<T, U>::value` defines when
409`mult_traits<T, U>::type` is valid.]
410
411[endsect]
412
413[section Compiler workarounds]
414
415Some compilers flag functions as ambiguous if the only
416distinguishing factor is a different condition in an enabler
417(even though the functions could never be ambiguous). For
418example, some compilers (e.g. GCC 3.2) diagnose the following
419two functions as ambiguous:
420
421``
422template <class T>
423typename enable_if<boost::is_arithmetic<T>, T>::type
424foo(T t);
425
426template <class T>
427typename disable_if<boost::is_arithmetic<T>, T>::type
428foo(T t);
429``
430
431Two workarounds can be applied:
432
433* Use an extra dummy parameter which disambiguates the
434 functions. Use a default value for it to hide the parameter
435 from the caller. For example:
436 ``
437 template <int> struct dummy { dummy(int) {} };
438
439 template <class T>
440 typename enable_if<boost::is_arithmetic<T>, T>::type
441 foo(T t, dummy<0> = 0);
442
443 template <class T>
444 typename disable_if<boost::is_arithmetic<T>, T>::type
445 foo(T t, dummy<1> = 0);
446 ``
447* Define the functions in different namespaces and bring them
448 into a common namespace with `using` declarations:
449 ``
450 namespace A {
451 template <class T>
452 typename enable_if<boost::is_arithmetic<T>, T>::type
453 foo(T t);
454 }
455
456 namespace B {
457 template <class T>
458 typename disable_if<boost::is_arithmetic<T>, T>::type
459 foo(T t);
460 }
461
462 using A::foo;
463 using B::foo;
464 ``
465 Note that the second workaround above cannot be used for
466 member templates. On the other hand, operators do not accept
467 extra arguments, which makes the first workaround unusable.
468 As the net effect, neither of the workarounds are of
469 assistance for templated operators that need to be defined as
470 member functions (assignment and subscript operators).
471
472[endsect]
473
474[endsect]
475
476[section Acknowledgements]
477
478We are grateful to Howard Hinnant, Jason Shirk, Paul
479Mensonides, and Richard Smith whose findings have
480influenced the library.
481
482[endsect]
483
484[section References]
485
486* [#REF1] \[1\] Jaakko J\u00E4rvi, Jeremiah Willcock, Howard
487 Hinnant, and Andrew Lumsdaine. Function overloading based on
488 arbitrary properties of types. /C++ Users Journal/,
489 21(6):25--32, June 2003.
490* [#REF2] \[2\] Jaakko J\u00E4rvi, Jeremiah Willcock, and
491 Andrew Lumsdaine. Concept-controlled polymorphism. In Frank
492 Pfennig and Yannis Smaragdakis, editors, /Generative
493 Programming and Component Engineering/, volume 2830 of
494 /LNCS/, pages 228--244. Springer Verlag, September 2003.
495* [#REF3] \[3\] David Vandevoorde and Nicolai M. Josuttis.
496 /C++ Templates: The Complete Guide/. Addison-Wesley, 2002.
497
498[endsect]
499
500[endsect]