Is `std::decay_t decay_copy(T&&)` equivalent to `auto decay_copy(auto&&)`? defines decay_copy as follows:

template<typename T>
std::decay_t<T> decay_copy(T&& v)
    return std::forward<T>(v);

I just wonder:

Is it equivalent to the following simpler one?

auto decay_copy(auto&& v)
    return v;


It wasn’t in 2011, because:

  • We didn’t have auto return type deduction for functions (that’s a C++14 feature), and
  • We didn’t have auto&& parameters for functions (that’s a C++20 feature), and
  • Rvalue references were not implicitly moved from in return statements (that’s also a C++20 feature)

But in C++20, yes, that is now a valid way to implement decay_copy. auto deduction does decay, return v; implicitly forwards, and everything else is the same.

I guess technically there’s an edge case like:

struct X {

With the original formulation of decay_copy(X{}), this is ill-formed (there’s no viable constructor for constructing an X from an rvalue X). With the new formulation under the existing C++20 rules, it becomes well formed and invokes the non-const copy constructor (because we do this two-step overload resolution).

If P2266 is adopted though, then they would be exactly equivalent because return v; would always treat v as an rvalue, exactly as the existing formulation does.