[英]Why isn't this templated move constructor being called?
我遇到了这种奇怪的情况:
template <typename pointed_t>
class MyPointer
{public:
MyPointer() : pPointed(nullptr) {}
/* PREVENT COMPILER-GENERATED FUNCTIONS */
MyPointer(const MyPointer&);
MyPointer(MyPointer&&);
MyPointer& operator=(const MyPointer&);
MyPointer& operator=(MyPointer&&);
//----------
pointed_t* pPointed;
/* COPY CONSTRUCTOR */
template <typename AnyPointerType>
MyPointer(AnyPointerType& other)
{
}
/* MOVE CONSTRUCTOR */
template <typename AnyPointerType>
MyPointer(AnyPointerType&& other)
{
}
};
int main()
{
MyPointer<char> p1;
MyPointer<char> p2 = p1; // COPY CONSTRUCTOR CALLED FINE
MyPointer<char> p3 = std::move(p1); // RAISES BELOW LINKER ERROR
/* Unresolved external symbol
public: __cdecl MyPointer<char>::MyPointer<char>(class MyPointer<char> &&)" */
}
所以 p2 = p1; 调用模板复制构造函数很好,但 p3 = std::move(p1); 不能调用模板化的移动构造函数?
所以结果是复制构造函数工作,但移动构造函数没有。 除非它是不同的类型:
MyPointer<float> p1;
MyPointer<char> p2 = std::move(p1); // NOW THE TEMPLATED MOVE CONSTRUCTOR IS CALLED FINE
有人可以帮我理解为什么没有调用模板化移动构造函数吗?
问题是从构造函数模板生成的构造函数永远不是复制/移动构造函数。
为什么复制构造函数不会失败?
因为您提供的用户声明的副本 ctor MyPointer::MyPointer(const MyPointer&)
具有const MyPointer&
类型的参数,但您提供的相应模板化构造函数具有AnyPointerType&
类型的参数。 请注意,后者没有低级const
。 所以当你写道:
MyPointer<char> p2 = p1; //this will use the template constructor that has no low-level const.
在上面,模板版本被选择而不是非模板移动 ctor,因为模板版本具有非常量参数并且p1
也是非常量。 您可以通过使p1
const
来确认是这种情况,在这种情况下,您将得到相同的链接器错误,但这次是复制 ctor。 演示
所以结果是复制构造函数工作,但移动构造函数没有。
MyPointer<char> p3 = std::move(p1);
不起作用,因为在这种情况下,您提供的用户声明的移动构造函数MyPointer(MyPointer&&)
具有MyPointer&&
类型的参数,并且相应的模板化 ctor 也具有参数MyPointer&&
。 所以写的时候:
MyPointer<char> p3 = std::move(p1); //the compiler prefers the non-template user-delcared move ctor
用户声明的非模板移动 ctor MyPointer::MyPointer(MyPointer&&)
优于模板版本,但由于用户声明的 ctor 没有实现,我们得到提到的链接器错误。
我想要我的模板调用。
在这种特殊情况下,有一个解决方案,如下所示。 特别是,我们可以在用户声明的 move ctor MyPointer::MyPointer(MyPointer&&)
的参数中添加一个低级const
。
template <typename pointed_t>
class MyPointer
{public:
MyPointer() : pPointed(nullptr) {}
/* PREVENT COMPILER-GENERATED FUNCTIONS */
MyPointer(const MyPointer&);
//------------vvvvv------------------>const added here
MyPointer(const MyPointer&&);
MyPointer& operator=(const MyPointer&);
MyPointer& operator=(MyPointer&&);
//----------
pointed_t* pPointed;
/* COPY CONSTRUCTOR */
template <typename AnyPointerType>
MyPointer(AnyPointerType& other)
{
std::cout<<"templated copy"<<std::endl;
}
/* MOVE CONSTRUCTOR */
template <typename AnyPointerType>
MyPointer(AnyPointerType&& other)
{
std::cout<<"template move"<<std::endl;
}
};
int main()
{
MyPointer<char> p1;
MyPointer<char> p2 = p1; //calls the templated version
MyPointer<char> p3 = std::move(p1); //calls the templated version
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.