8

http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2011/n3255.html 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;
}
TylerH
  • 20,799
  • 66
  • 75
  • 101
xmllmx
  • 39,765
  • 26
  • 162
  • 323

1 Answers1

16

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 {
    X();
    X(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.

Barry
  • 286,269
  • 29
  • 621
  • 977