perfect forwarding in constructors (C++17)

  • A+
Category:Languages

Consider the following code

struct A {     A(int id) : id_ { id } {}      A(const A& rhs) { std::cout << "cctor from " +         std::to_string(rhs.id_) << std::endl; }     A(A&& rhs) { std::cout << "mctor from " +         std::to_string(rhs.id_) << std::endl; }      int id_; };  template<typename T> struct B1 {     constexpr B1(T&& x) noexcept : x_ { std::forward<T>(x) } {}      T x_; };  template<typename T> struct B2 {     constexpr B2(T&& x) noexcept;      T x_; };  template<typename T> constexpr B2<T>::B2(     T&& x ) noexcept :     x_ { std::forward<T>(x) } { }  int main( ) {     A a { 1 };      //B1 b11 { a }; // not compiling     B1 b12 { A { 2 } };      B2 b21 { a };     B2 b22 { A { 3 } };      return 0;  } 

which yields

mctor from 2 mctor from 3 

So it basically looks as if the externally defined constructor perfectly forwards the value category of its argument while the inline-defined constructor does not.

Is it that an externally defined constructor is handled like a function template (which perfectly forwards its arguments) or what's going on here?

Links to the appropriate section of the standard would be welcome.

Using gcc 7.2.0

 


It's a GCC bug. Forwarding references have a very clear cut definition:

[temp.deduct.call] (emphasis mine)

3 A forwarding reference is an rvalue reference to a cv-unqualified template parameter that does not represent a template parameter of a class template (during class template argument deduction ([over.match.class.deduct])). If P is a forwarding reference and the argument is an lvalue, the type “lvalue reference to A” is used in place of A for type deduction.

In both cases T names a template parameter of the enclosing class during CTAD, so it should not produce a forwarding reference either way. The c'tor being defined inline or outside the class definition has no bearing on this.

Comment

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: