Search code examples
c++c++14trailing-return-typereturn-type-deduction

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?


Solution

  • 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