]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/type_traits/doc/common_type.qbk
bump version to 12.2.2-pve1
[ceph.git] / ceph / src / boost / libs / type_traits / doc / common_type.qbk
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 [/===================================================================]
11 [section:common_type common_type]
12 [/===================================================================]
13
14 __header ` #include <boost/type_traits/common_type.hpp>` or ` #include <boost/type_traits.hpp>`
15
16 namespace boost {
17 template <class... T> struct common_type;
18 }
19
20
21 `common_type` is a traits class used to deduce a type common to a several types, useful as the return type of functions
22 operating on multiple input types such as in mixed-mode arithmetic..
23
24 The nested typedef `::type` could be defined as follows:
25
26 template <class... T>
27 struct common_type;
28
29 template <class T, class U, class... V>
30 struct common_type<T, U, V...> {
31 typedef typename common_type<typename common_type<T, U>::type, V...>::type type;
32 };
33
34 template <>
35 struct common_type<> {
36 };
37
38 template <class T>
39 struct common_type<T> {
40 typedef typename __decay<T>::type type;
41 };
42
43 template <class T, class U>
44 struct common_type<T, U> {
45 typedef typename __decay<
46 decltype( __declval<bool>()?
47 __declval<typename __decay<T>::type>():
48 __declval<typename __decay<U>::type>() )
49 >::type type;
50 };
51
52 All parameter types must be complete. This trait is permitted to be specialized by a user if at least one
53 template parameter is a user-defined type. [*Note:] Such specializations are required when only explicit conversions
54 are desired among the `common_type` arguments.
55
56 Note that when the compiler does not support variadic templates (and the macro `BOOST_NO_CXX11_VARIADIC_TEMPLATES` is defined)
57 then the maximum number of template arguments is 9.
58
59
60 [h4 Tutorial]
61
62 In a nutshell, `common_type` is a trait that takes 1 or more types, and returns a type which
63 all of the types will convert to. The default definition demands this conversion be implicit.
64 However the trait can be specialized for user-defined types which want to limit their inter-type conversions to explicit,
65 and yet still want to interoperate with the `common_type` facility.
66
67 [*Example:]
68
69 template <class T, class U>
70 complex<typename common_type<T, U>::type>
71 operator+(complex<T>, complex<U>);
72
73
74 In the above example, "mixed-mode" complex arithmetic is allowed. The return type is described by `common_type`.
75 For example the resulting type of adding a `complex<float>` and `complex<double>` might be a `complex<double>`.
76
77 Here is how someone might produce a variadic comparison function:
78
79 template <class ...T>
80 typename common_type<T...>::type
81 min(T... t);
82
83 This is a very useful and broadly applicable utility.
84
85 [h4 How to get the common type of types with explicit conversions?]
86
87 Another choice for the author of the preceding operator could be
88
89 template <class T, class U>
90 typename common_type<complex<T>, complex<U> >::type
91 operator+(complex<T>, complex<U>);
92
93 As the default definition of `common_type` demands the conversion be implicit, we need to specialize the trait for complex types as follows.
94
95 template <class T, class U>
96 struct common_type<complex<T>, complex<U> > {
97 typedef complex< common_type<T, U> > type;
98 };
99
100 [h4 How important is the order of the `common_type<>` template arguments?]
101
102 The order of the template parameters is important.
103
104 `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`.
105
106 Consider
107
108 struct A {};
109 struct B {};
110 struct C {
111 C() {}
112 C(A const&) {}
113 C(B const&) {}
114 C& operator=(C const&) {
115 return *this;
116 }
117 };
118
119 The following doesn't compile
120
121 typedef boost::common_type<A, B, C>::type ABC; // Does not compile
122
123 while
124
125 typedef boost::common_type<C, A, B>::type ABC;
126
127 compiles.
128
129 Thus, as `common_type<A,B>::type` is undefined, `common_type<A,B,C>::type` is also undefined.
130
131 It is intended that clients who wish for `common_type<A, B>` to be well
132 defined to define it themselves:
133
134 namespace boost
135 {
136
137 template <>
138 struct common_type<A, B> {typedef C type;};
139
140 }
141
142 Now this client can ask for `common_type<A, B, C>` (and get
143 the same answer).
144
145 Clients wanting to ask `common_type<A, B, C>` in any order and get the same result need to add in addition:
146
147 namespace boost
148 {
149
150 template <> struct common_type<B, A>
151 : public common_type<A, B> {};
152
153 }
154
155 This is needed as the specialization of `common_type<A, B>` is not be used implicitly for `common_type<B, A>`.
156
157 [h4 Can the `common_type` of two types be a third type?]
158
159 Given the preceding example, one might expect `common_type<A,B>::type` to be `C` without any intervention from the user.
160 But the default `common_type<>` implementation doesn't grant that. It is intended that clients who wish for `common_type<A, B>`
161 to be well defined to define it themselves:
162
163 namespace boost
164 {
165
166 template <>
167 struct common_type<A, B> {typedef C type;};
168
169 template <> struct common_type<B, A>
170 : public common_type<A, B> {};
171
172 }
173
174 Now this client can ask for `common_type<A, B>`.
175
176 [h4 How does `common_type` behave with pointers?]
177
178 Consider
179
180 struct C { }:
181 struct B : C { };
182 struct A : C { };
183
184
185 Shouldn't `common_type<A*,B*>::type` be `C*`? I would say yes, but the default implementation will make it ill-formed.
186
187 The library could add a specialization for pointers, as
188
189 namespace boost
190 {
191
192 template <typename A, typename B>
193 struct common_type<A*, B*> {
194 typedef common_type<A, B>* type;
195 };
196 }
197
198 But in the absence of a motivating use cases, we prefer not to add more than the standard specifies.
199
200 Of course the user can always make this specialization.
201
202 [h4 Can you explain the pros/cons of `common_type` against Boost.Typeof?]
203
204 Even if they appear to be close, `common_type` and `typeof` have
205 different purposes. You use `typeof` to get the type of an expression, while
206 you use `common_type` to set explicitly the type returned of a template
207 function. Both are complementary, and indeed `common_type` is approximately equivalent to
208 `decltype(__declval<bool>() ? __declval<T>() : __declval<U>())`.
209
210 `common_type` is also similar to `promote_args<class ...T>` in `boost/math/tools/promotion.hpp`,
211 though it is not exactly the same as `promote_args` either. `common_type<T1, T2>::type` simply represents the result of some
212 operation on `T1` and `T2`, and defaults to the type obtained by putting `T1` and `T2` into a conditional statement.
213
214 It is meant to be customizable (via specialization) if this default is not appropriate.
215
216 [endsect]
217