Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

auto, decltype(auto) and trailing return type

Is there a difference between:

template <class T>
constexpr decltype(auto) f(T&& x) -> decltype(std::get<0>(std::forward<T>(x)))
{
    return std::get<0>(std::forward<T>(x));
}

and:

template <class T>
constexpr auto f(T&& x) -> decltype(std::get<0>(std::forward<T>(x)))
{
    return std::get<0>(std::forward<T>(x));
}

and if so, what is it, and which one should I use for perfect forwarding?

like image 209
Vincent Avatar asked Mar 09 '23 15:03

Vincent


1 Answers

Trailing return type should only be used with auto

The point of decltype(auto) vs auto is to distinguish the case whether the return type should be a reference or value. But in your case the return type is already explicitly defined as decltype(std::get<0>(std::forward<T>(x))), so it will be perfectly-forwarded even if you use auto.

In auto f() -> T, the "auto" keyword is simply a syntactic construct to fill in a type position. It serves no other purpose.


In fact, in C++17 you cannot use a decltype(auto) with trailing-return-type together.

C++14 wordings (n3936 §7.1.6.4[dcl.spec.auto]/1):

The auto and decltype(auto) type-specifiers designate a placeholder type that will be replaced later, either by deduction from an initializer or by explicit specification with a trailing-return-type. The auto type-specifier is also used to signify that a lambda is a generic lambda.

C++17 wordings (n4618 §7.1.7.4[dcl.spec.auto]/1):

The auto and decltype(auto) type-specifiers are used to designate a placeholder type that will be replaced later by deduction from an initializer. The auto type-specifier is also used to introduce a function type having a trailing-return-type or to signify that a lambda is a generic lambda (5.1.5). The auto type-specifier is also used to introduce a decomposition declaration (8.5).

This is DR 1852, see Does a placeholder in a trailing-return-type override an initial placeholder?.

Practically, while gcc accepts decltype(auto) f() -> T (which is a bug), but clang will reject it saying

error: function with trailing return type must specify return type 'auto',
not 'decltype(auto)'
like image 77
kennytm Avatar answered Mar 12 '23 04:03

kennytm