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?
MyPointer(MyPointer&&);
defined? – RecoilMyPointer::MyPointer(MyPointer&&)
is preferred over the corresponding templated version. But since there is no implementation available for the non-template version we get the linker error. On the other hand, forMyPointer<char> p2 = p1;
the templated version is a better match than the nontemplate versionMyPointer::MyPointer(const MyPointer&)
as the argument passedp1
is nonconst and so the templated version is selected. – Sainted