Fitzwilliam Bennet-Darcy Fitzwilliam Bennet-Darcy - 3 months ago 10
C++ Question

Can a templatised constructor stand in for a deleted copy constructor?

Consider

template<typename T>
struct Foo
{
Foo(const Foo&) = delete;
template <typename Y>
Foo(const Foo<Y>&){}
};


Does the appropriate instantiation of the template constructor stand in for the copy constructor? I know it doesn't normally (since the copy constructor must not be a template function) but here I've deleted the copy constructor.

Answer

No it can't: overload resolution always considers non-templated functions first, and when a deleted one is encountered, overload resolution fails rather than a template overload being considered.

Allow me to introduce the default constructor into your class with the line

Foo() = default;

Then, consider two variables

Foo<double> double_foo;
Foo<int> int_foo;

Then note

  1. Foo<int> bar(double_foo); is allowed due to the template
  2. Foo<int> bar(int_foo); is not allowed due to the deleted constructor
  3. Foo<int> bar = Foo<int>(); would be allowed if you had re-introduced the move constructor by writing Foo(const Foo&&) = default;. You need to use the = syntax here since Foo<int> bar(Foo<int>()); is a forward declaration.

Finally, your assertion "the copy constructor must not be a template function" is not correct. Credit to @LightnessRacesInOrbit:

C++14 12.8.2 "A non-template constructor for class X is a copy constructor if its first parameter is of type X&, const X&, volatile X& or const volatile X&, and either there are no other parameters or else all other parameters have default arguments (8.3.6).