[/ Copyright 2008 Howard Hinnant Copyright 2008 Beman Dawes Copyright 2010 John Maddock Distributed under the Boost Software License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt). ] [/===================================================================] [section:common_type common_type] [/===================================================================] __header ` #include ` or ` #include ` namespace boost { template struct common_type; template using common_type_t = typename common_type::type; // C++11 and above } `common_type` is a traits class used to deduce a type common to a several types, useful as the return type of functions operating on multiple input types such as in mixed-mode arithmetic.. The nested typedef `::type` could be defined as follows: template struct common_type; template struct common_type { typedef typename common_type::type, V...>::type type; }; template <> struct common_type<> { }; template struct common_type { typedef typename __decay::type type; }; template struct common_type { typedef typename __decay< decltype( __declval()? __declval::type>(): __declval::type>() ) >::type type; }; All parameter types must be complete. This trait is permitted to be specialized by a user if at least one template parameter is a user-defined type. [*Note:] Such specializations are required when only explicit conversions are desired among the `common_type` arguments. Note that when the compiler does not support variadic templates (and the macro `BOOST_NO_CXX11_VARIADIC_TEMPLATES` is defined) then the maximum number of template arguments is 9. [h4 Tutorial] In a nutshell, `common_type` is a trait that takes 1 or more types, and returns a type which all of the types will convert to. The default definition demands this conversion be implicit. However the trait can be specialized for user-defined types which want to limit their inter-type conversions to explicit, and yet still want to interoperate with the `common_type` facility. [*Example:] template complex::type> operator+(complex, complex); In the above example, "mixed-mode" complex arithmetic is allowed. The return type is described by `common_type`. For example the resulting type of adding a `complex` and `complex` might be a `complex`. Here is how someone might produce a variadic comparison function: template typename common_type::type min(T... t); This is a very useful and broadly applicable utility. [h4 How to get the common type of types with explicit conversions?] Another choice for the author of the preceding operator could be template typename common_type, complex >::type operator+(complex, complex); As the default definition of `common_type` demands the conversion be implicit, we need to specialize the trait for complex types as follows. template struct common_type, complex > { typedef complex< common_type > type; }; [h4 How important is the order of the `common_type<>` template arguments?] The order of the template parameters is important. `common_type::type` is not equivalent to `common_type::type`, but to `common_type::type, C>::type`. Consider struct A {}; struct B {}; struct C { C() {} C(A const&) {} C(B const&) {} C& operator=(C const&) { return *this; } }; The following doesn't compile typedef boost::common_type::type ABC; // Does not compile while typedef boost::common_type::type ABC; compiles. Thus, as `common_type::type` is undefined, `common_type::type` is also undefined. It is intended that clients who wish for `common_type` to be well defined to define it themselves: namespace boost { template <> struct common_type {typedef C type;}; } Now this client can ask for `common_type` (and get the same answer). Clients wanting to ask `common_type` in any order and get the same result need to add in addition: namespace boost { template <> struct common_type : public common_type {}; } This is needed as the specialization of `common_type` is not be used implicitly for `common_type`. [h4 Can the `common_type` of two types be a third type?] Given the preceding example, one might expect `common_type::type` to be `C` without any intervention from the user. But the default `common_type<>` implementation doesn't grant that. It is intended that clients who wish for `common_type` to be well defined to define it themselves: namespace boost { template <> struct common_type {typedef C type;}; template <> struct common_type : public common_type {}; } Now this client can ask for `common_type`. [h4 How does `common_type` behave with pointers?] Consider struct C { }: struct B : C { }; struct A : C { }; Shouldn't `common_type::type` be `C*`? I would say yes, but the default implementation will make it ill-formed. The library could add a specialization for pointers, as namespace boost { template struct common_type { typedef common_type* type; }; } But in the absence of a motivating use cases, we prefer not to add more than the standard specifies. Of course the user can always make this specialization. [h4 Can you explain the pros/cons of `common_type` against Boost.Typeof?] Even if they appear to be close, `common_type` and `typeof` have different purposes. You use `typeof` to get the type of an expression, while you use `common_type` to set explicitly the type returned of a template function. Both are complementary, and indeed `common_type` is approximately equivalent to `decltype(__declval() ? __declval() : __declval())`. `common_type` is also similar to `promote_args` in `boost/math/tools/promotion.hpp`, though it is not exactly the same as `promote_args` either. `common_type::type` simply represents the result of some operation on `T1` and `T2`, and defaults to the type obtained by putting `T1` and `T2` into a conditional statement. It is meant to be customizable (via specialization) if this default is not appropriate. [endsect]