简体   繁体   中英

Legitimate uses of the trailing return type syntax as of C++14

Is there actually any reason to use the following syntax anymore :

template<typename T>
auto access(T& t, int i)
  -> decltype(t[i])
{
    return t[i];
}

Now that we can use :

template<typename T>
decltype(auto) access(T& t, int i)
{
    return t[i];
}

The trailing return type syntax now seems a little redundant?

Deduced return types are not SFINAE friendly. This overload will simply drop out of the overload set if t[i] is invalid:

template<typename T>
auto access(T& t, int i)
  -> decltype(t[i])
{
    return t[i];
}

Whereas this overload will not, leading to a hard error:

template<typename T>
decltype(auto) access(T& t, int i)
{
    return t[i];
}

Demo


Also, you can run into issues with conflicting deduced return types. Consider if I wanted to return a std::optional<T> . The following code doesn't compile since std::nullopt_t is not the same type as std::optional<T> :

#include <optional> // C++17 standard library feature

template <typename T>
auto foo(T const& val)
{
    if (val.is_invalid()) return std::nullopt;
    return val.some_function_returning_an_optional();
}

Trailing return types let you specify exactly which expressions' type to return:

template <typename T>
auto foo(T const& val)
    -> decltype(val.some_function_returning_an_optional())
{
    if (val.is_invalid()) return std::nullopt;
    return val.some_function_returning_an_optional();
}

You could use a leading return type, but it would require the use of std::declval , which makes it harder to understand:

template <typename T>
decltype(std::declval<T const&>().some_function_returning_an_optional())
foo(T const& val)
{
    if (val.is_invalid()) return std::nullopt;
    return val.some_function_returning_an_optional();
}

Demo

Yes, at least three reasons:

  1. Meaningful declaration : Your first variant has a declaration which tells me what the return type is; your second variant requires that I read your definition . But your definition might be in another file, or not very clear.
  2. Type constraint or type conversion : Your body could be returning something other than the expression T[i] , and thus you get a type constraint or a conversion from what the body returns to what you want to get.
  3. Backwards compatibility : This may seem trivial to you, but try writing a library and telling your users "Oh, you need a C++14-conformant compiler because of my cute syntax choices".

And there's also a fourth reason in Justin's answer .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM