为什么不称呼这个模板的移动构造函数?
我遇到了这种奇怪的情况:
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
有人可以帮助我理解为什么未调用模板的移动构造函数?
I've run into this weird situation:
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> &&)" */
}
So p2 = p1; calls the templated copy constructor fine, but p3 = std::move(p1); can't call the templated move constructor?
So the result is that the copy constructor works, but the move constructor doesn't. Unless it's of a different type:
MyPointer<float> p1;
MyPointer<char> p2 = std::move(p1); // NOW THE TEMPLATED MOVE CONSTRUCTOR IS CALLED FINE
Can someone please help me understand why the templated move constructor is not being called?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
问题是,从构造函数模板生成的构造函数绝不是复制/移动构造函数。
因为用户指定复制ctor
mypointer :: mypointer(const mypointer&amp;)
您提供的参数具有类型const mypointer&const mypointer&amp;
,但您提供的相应的模板构造函数类型anypoInterType&amp;
的参数。注意后者没有低级const
。因此,当您编写时:在上面的情况下,模板版本是通过 nontemplate move ctor,因为模板版本具有非const参数,
p1
也是nonconst。您可以通过制作p1
const
来确认这种情况,在这种情况下,您会遇到相同的链接器错误,但是这次是复制CTOR。 demomypointer&lt; char&gt; p3 = std :: move(p1);
不起作用,因为在这种情况下,您提供的用户指定移动构造函数mypointer(mypointer&amp;&amp;&amp;)
具有类型的参数mypointer&amp;&amp;
,相应的模板CTOR也具有参数mypointer&amp;&amp;
。因此,在写作时:非模板移动ctor
mypointer :: mypointer(mypointer&amp;&amp;&amp;)
用户删除是优先 the user-声明为CTOR没有实现,我们会收到上述链接器错误。解决方案
在这种特殊情况下,有一个解决方案,如下所示。特别是,我们可以在用户声明的参数中添加低级
const
MOVE CTORmypointer :: mypointer(mypointer&amp;&amp;&amp;&amp;)
。工作演示
The problem is that a constructor generated from a constructor template is never a copy/move constructor.
Because the user-declared copy ctor
MyPointer::MyPointer(const MyPointer&)
that you provided has a parameter of typeconst MyPointer&
but the corresponding templated constructor that you provided has the parameter of typeAnyPointerType&
. Note in the latter there is no low-levelconst
. And so when you wrote:In the above, the template version is chosen over the non-template move ctor as the templated version has a non-const parameter and
p1
is also nonconst. You can confirm that this is the case by makingp1
const
in which case you will get the same linker error but this time for the copy ctor. DemoThe
MyPointer<char> p3 = std::move(p1);
doesn't work because in this case the user-declared move constructorMyPointer(MyPointer&&)
that you provided has a parameter of typeMyPointer&&
and the corresponding templated ctor also has the parameterMyPointer&&
. And so when writing:The non template move ctor
MyPointer::MyPointer(MyPointer&&)
that was user-declared is preferred over the templated version but since the user-declared ctor doesn't have an implementation we get the mentioned linker error.Solution
In this particular case there is a solution as shown below. In particular, we can add a low-level
const
in the parameter of the user declared move ctorMyPointer::MyPointer(MyPointer&&)
.Working demo