考虑下面的代码
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;
}
产生
mctor from 2
mctor from 3
所以它基本上看起来好像外部定义的构造函数完美地转发了其参数的值类别,而内联定义的构造函数却没有。
外部定义的构造函数是像函数模板一样处理(完美地转发其参数)还是这里发生了什么?
欢迎提供标准相应部分的链接。
我使用的是 GCC 7.2.0。
最佳答案
这是一个 GCC 错误。转发引用有一个非常明确的定义:
[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.
在这两种情况下,T
在 CTAD 期间命名封闭类的模板参数,因此它不应该产生任何一种转发引用。内联或在类定义之外定义的 c'tor 与此无关。
关于c++ - 构造函数中的完美转发 (C++17),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53519699/