enable_if.qbk 16 KB

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