When I look into a code snippet for a possible implementation of std::common_type
template <class ...T> struct common_type;
template <class T>
struct common_type<T> {
typedef decay_t<T> type;
};
template <class T, class U>
struct common_type<T, U> {
typedef decay_t<decltype(true ? declval<T>() : declval<U>())> type;
};
template <class T, class U, class... V>
struct common_type<T, U, V...> {
typedef common_type_t<common_type_t<T, U>, V...> type;
};
The part how to get a common type for two template argument makes me confused.It is a usage of ternary operator with decltype.
As I known, whether to return the second or third operand is decided by the value of first operand. In this snippet, the first operand is true which means the return value of expression will always be declval<T>()
. If it is what i thought which make no sense... Therefore, I have tried the following test
int iii = 2;
float fff = 3.3;
std::cout << typeid(decltype(false? std::move(iii):std::move(fff))).name() << std::endl;
std::cout << typeid(decltype(std::move(iii))).name() << std::endl;
std::cout << typeid(decltype(false ? iii : fff)).name() << std::endl;
std::cout << typeid(decltype(true ? iii : fff)).name() << std::endl;
// [02:23:37][ryu@C++_test]$ g++ -std=c++14 -g common_type.cpp
// output
// f
// i
// f
// f
Comparing with the running result, The result what i though should be like as follows
int iii = 2;
float fff = 3.3;
std::cout << typeid(decltype(false ? iii : fff)).name() << std::endl; // should return f;
std::cout << typeid(decltype(true ? iii : fff)).name() << std::endl; // should return i;
Anyone when can help to explain why the running result is different ?
In other words, what's the return result of decltype when it is applied on a ternary expression?
The decltype type specifier yields the type of a specified expression. The decltype type specifier, together with the auto keyword, is useful primarily to developers who write template libraries. Use auto and decltype to declare a function template whose return type depends on the types of its template arguments.
Conditional AND The operator is applied between two Boolean expressions. It is denoted by the two AND operators (&&). It returns true if and only if both expressions are true, else returns false.
Decltype gives the type information at compile time while typeid gives at runtime. So, if we have a base class reference (or pointer) referring to (or pointing to) a derived class object, the decltype would give type as base class reference (or pointer, but typeid would give the derived type reference (or pointer).
decltype is a compile time evaluation (like sizeof ), and so can only use the static type.
The type of an expression is a compile-time property. The value of the first operand in a conditional expression (and hence the branch selected), is, in general, a run-time thing, so it can't possibly affect the expression's type.
Instead, a complicated set of rules (more than a page of standardese, most of which I quoted in this answer) is used to determine what the "common type" of the second and third operands is, and the conditional expression is of that type. std::common_type
merely leverages the existing rules in the core language.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With