Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Return type of decltype when applied to ternary(?:) expression

Tags:

c++

c++11

c++14

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?

like image 981
ryu Avatar asked May 06 '15 18:05

ryu


People also ask

What does decltype return?

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.

What is return type of conditional operator?

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.

How does decltype work in C++?

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).

Is decltype runtime or compile time?

decltype is a compile time evaluation (like sizeof ), and so can only use the static type.


1 Answers

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.

like image 86
T.C. Avatar answered Nov 15 '22 19:11

T.C.