繁体   English   中英

为什么不调用这个模板化的移动构造函数?

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM