Given types A,B, I am concerned with the exact definition of std::common_type<A,B>, disregarding the variadic case std::common_type<A...> for arbitrary types A.... So let
using T = decltype(true ? std::declval<A>() : std::declval<B>());
using C = std::common_type<A,B>;
Now, according to a number of sources, I have found the following relations (skipping typename for brevity):
cppreference.com:
C::type = std::decay<T>::typecplusplus.com:
C::type = TGCC 4.8.1
<type_traits>implementation:C::type = std::decay<T>::typeifTis valid, otherwiseCdoes not contain a::typemember ("SFINAE-friendly")Clang 3.3
<type_traits>implementation:C::type = std::remove_reference<T>::type
I find the "SFINAE-friendly" version of GCC a minor detail, while std::remove_reference and std::decay practically only differ in built-in arrays and functions, plus cv-qualification, for which again I am not concerned much. So my question is
Should it be decay<T>::type or just T? What is the rationale of using decay<T>::type? Is it only about representing result A() + B() e.g. for arithmetic expressions?
For instance, experimenting a bit, I have found that in the case of the "just T" definition, we have
common_type<int&,int&> = int&
common_type<int&,long&> = long
that is, an lvalue reference is maintained if types are equal. This reflects the fact that
int a, b;
(true ? a : b) = 0;
is valid, while
int a;
long b;
(true ? a : b) = 0;
is not. This semantics of "allowing assignment if types are equal" is exactly what I need in one application, and I tend to believe that common_type and decay should be two independent steps. Should I just use my own definitions?
should std::common_type use std::decay?
Yes, see Library Working Group Defect #2141.
Short version (long version, see link above):
declval<A>()returns aA&&common_typeis specified viadeclval, n3337:template <class T, class U> struct common_type<T, U> { typedef decltype(true ? declval<T>() : declval<U>()) type; };common_type<int, int>::typetherefore yieldsint&&, which is unexpectedproposed resolution is to add
decaytemplate <class T, class U> struct common_type<T, U> { typedef decay_t < decltype(true ? declval<T>() : declval<U>()) > type; };common_type<int, int>::typenow yieldsint
来源:https://stackoverflow.com/questions/21975812/should-stdcommon-type-use-stddecay