common_type.qbk 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218
  1. [/
  2. Copyright 2008 Howard Hinnant
  3. Copyright 2008 Beman Dawes
  4. Copyright 2010 John Maddock
  5. Distributed under the Boost Software License, Version 1.0.
  6. (See accompanying file LICENSE_1_0.txt or copy at
  7. http://www.boost.org/LICENSE_1_0.txt).
  8. ]
  9. [/===================================================================]
  10. [section:common_type common_type]
  11. [/===================================================================]
  12. __header ` #include <boost/type_traits/common_type.hpp>` or ` #include <boost/type_traits.hpp>`
  13. namespace boost {
  14. template <class... T> struct common_type;
  15. template<class... T> using common_type_t = typename common_type<T...>::type; // C++11 and above
  16. }
  17. `common_type` is a traits class used to deduce a type common to a several types, useful as the return type of functions
  18. operating on multiple input types such as in mixed-mode arithmetic..
  19. The nested typedef `::type` could be defined as follows:
  20. template <class... T>
  21. struct common_type;
  22. template <class T, class U, class... V>
  23. struct common_type<T, U, V...> {
  24. typedef typename common_type<typename common_type<T, U>::type, V...>::type type;
  25. };
  26. template <>
  27. struct common_type<> {
  28. };
  29. template <class T>
  30. struct common_type<T> {
  31. typedef typename __decay<T>::type type;
  32. };
  33. template <class T, class U>
  34. struct common_type<T, U> {
  35. typedef typename __decay<
  36. decltype( __declval<bool>()?
  37. __declval<typename __decay<T>::type>():
  38. __declval<typename __decay<U>::type>() )
  39. >::type type;
  40. };
  41. All parameter types must be complete. This trait is permitted to be specialized by a user if at least one
  42. template parameter is a user-defined type. [*Note:] Such specializations are required when only explicit conversions
  43. are desired among the `common_type` arguments.
  44. Note that when the compiler does not support variadic templates (and the macro `BOOST_NO_CXX11_VARIADIC_TEMPLATES` is defined)
  45. then the maximum number of template arguments is 9.
  46. [h4 Tutorial]
  47. In a nutshell, `common_type` is a trait that takes 1 or more types, and returns a type which
  48. all of the types will convert to. The default definition demands this conversion be implicit.
  49. However the trait can be specialized for user-defined types which want to limit their inter-type conversions to explicit,
  50. and yet still want to interoperate with the `common_type` facility.
  51. [*Example:]
  52. template <class T, class U>
  53. complex<typename common_type<T, U>::type>
  54. operator+(complex<T>, complex<U>);
  55. In the above example, "mixed-mode" complex arithmetic is allowed. The return type is described by `common_type`.
  56. For example the resulting type of adding a `complex<float>` and `complex<double>` might be a `complex<double>`.
  57. Here is how someone might produce a variadic comparison function:
  58. template <class ...T>
  59. typename common_type<T...>::type
  60. min(T... t);
  61. This is a very useful and broadly applicable utility.
  62. [h4 How to get the common type of types with explicit conversions?]
  63. Another choice for the author of the preceding operator could be
  64. template <class T, class U>
  65. typename common_type<complex<T>, complex<U> >::type
  66. operator+(complex<T>, complex<U>);
  67. As the default definition of `common_type` demands the conversion be implicit, we need to specialize the trait for complex types as follows.
  68. template <class T, class U>
  69. struct common_type<complex<T>, complex<U> > {
  70. typedef complex< common_type<T, U> > type;
  71. };
  72. [h4 How important is the order of the `common_type<>` template arguments?]
  73. The order of the template parameters is important.
  74. `common_type<A,B,C>::type` is not equivalent to `common_type<C,A,B>::type`, but to `common_type<common_type<A,B>::type, C>::type`.
  75. Consider
  76. struct A {};
  77. struct B {};
  78. struct C {
  79. C() {}
  80. C(A const&) {}
  81. C(B const&) {}
  82. C& operator=(C const&) {
  83. return *this;
  84. }
  85. };
  86. The following doesn't compile
  87. typedef boost::common_type<A, B, C>::type ABC; // Does not compile
  88. while
  89. typedef boost::common_type<C, A, B>::type ABC;
  90. compiles.
  91. Thus, as `common_type<A,B>::type` is undefined, `common_type<A,B,C>::type` is also undefined.
  92. It is intended that clients who wish for `common_type<A, B>` to be well
  93. defined to define it themselves:
  94. namespace boost
  95. {
  96. template <>
  97. struct common_type<A, B> {typedef C type;};
  98. }
  99. Now this client can ask for `common_type<A, B, C>` (and get
  100. the same answer).
  101. Clients wanting to ask `common_type<A, B, C>` in any order and get the same result need to add in addition:
  102. namespace boost
  103. {
  104. template <> struct common_type<B, A>
  105. : public common_type<A, B> {};
  106. }
  107. This is needed as the specialization of `common_type<A, B>` is not be used implicitly for `common_type<B, A>`.
  108. [h4 Can the `common_type` of two types be a third type?]
  109. Given the preceding example, one might expect `common_type<A,B>::type` to be `C` without any intervention from the user.
  110. But the default `common_type<>` implementation doesn't grant that. It is intended that clients who wish for `common_type<A, B>`
  111. to be well defined to define it themselves:
  112. namespace boost
  113. {
  114. template <>
  115. struct common_type<A, B> {typedef C type;};
  116. template <> struct common_type<B, A>
  117. : public common_type<A, B> {};
  118. }
  119. Now this client can ask for `common_type<A, B>`.
  120. [h4 How does `common_type` behave with pointers?]
  121. Consider
  122. struct C { }:
  123. struct B : C { };
  124. struct A : C { };
  125. Shouldn't `common_type<A*,B*>::type` be `C*`? I would say yes, but the default implementation will make it ill-formed.
  126. The library could add a specialization for pointers, as
  127. namespace boost
  128. {
  129. template <typename A, typename B>
  130. struct common_type<A*, B*> {
  131. typedef common_type<A, B>* type;
  132. };
  133. }
  134. But in the absence of a motivating use cases, we prefer not to add more than the standard specifies.
  135. Of course the user can always make this specialization.
  136. [h4 Can you explain the pros/cons of `common_type` against Boost.Typeof?]
  137. Even if they appear to be close, `common_type` and `typeof` have
  138. different purposes. You use `typeof` to get the type of an expression, while
  139. you use `common_type` to set explicitly the type returned of a template
  140. function. Both are complementary, and indeed `common_type` is approximately equivalent to
  141. `decltype(__declval<bool>() ? __declval<T>() : __declval<U>())`.
  142. `common_type` is also similar to `promote_args<class ...T>` in `boost/math/tools/promotion.hpp`,
  143. though it is not exactly the same as `promote_args` either. `common_type<T1, T2>::type` simply represents the result of some
  144. operation on `T1` and `T2`, and defaults to the type obtained by putting `T1` and `T2` into a conditional statement.
  145. It is meant to be customizable (via specialization) if this default is not appropriate.
  146. [endsect]