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] 501