Orient Orient - 1 month ago 14
C++ Question

What is difference between decltype(auto) and decltype(returning expr) as return type?

What is the difference between

decltype(auto)
and
decltype(returning expression)
as return type of a function (template) if
expr
used without parentheses in both cases?

auto f() -> decltype(auto) { return expr; } // 1
auto f() -> decltype(expr) { return expr; } // 2


Above
f
can be defined/declared in any context and can be either (member) function or (member) function template, or even (generic) lambda.
expr
can depend on any template parameters.

In second version both
expr
are exactly the same expression without extra parentheses.

Which differences can one expect, using first or second form in C++14 and later?

What if parentheses used everywhere?

Answer

Yes there is a difference. The first one will detect the return type based on the return expression in the body of the function.

The second one will not also set the return type to the type of the expression inside decltype(), but will also apply expression sfinae on it. That means that if the expression inside decltype is not valid, the compiler will search for another valid overload. Whereas the first version will be a hard error.

Take this example:

template<typename T>
auto fun(T a) -> decltype(a.f()) { return a.f(); }

template<typename T>
auto fun(T a) -> decltype(a.g()) { return a.g(); }

struct SomeType {
    int g() { return 0; }
};

fun(SomeType{});

This select the correct overload. Now if we replace decltype(expr) by decltype(auto), the compiler will not be able to select the correct overload, as there's nothing in the function signature that constrains what the type is supposed to be able to do.

Comments