If we do not delete the copy ctor, the generated copy ctor is called instead of the member template. Quite unexpected!
if we delete the copy ctor receiving a const&, then the program does not call the member template
but, if we delete the copy ctor receiving a const volatile& as above then the member template is invoked "as if it were a copy ctor".... but why in this case and not in the others?
If we do not delete the copy ctor, the generated copy ctor is called instead of the member template. Quite unexpected!
I guess you mean if you comment out line 10? You'll have a class with implicit copy constructor taking const C& and ordinary constructor taking const T&. Non-template beats template.
if we delete the copy ctor receiving a const&, then the program does not call the member template
I guess you mean if you remove the word 'volatile' from line 10? Tou have a class with copy constructor taking const C&, and ordinary constructor taking const T&. Non-template beats template, overload resolution picks the copy ctor, compilation fails because it's deleted.
if we delete the copy ctor receiving a const volatile& as above then the member template is invoked "
The class has a copy constructor taking const volatile C& and ordinary constructor taking const T&. If the argument is volatile, the copy ctor is chosen (and compilation fails). If the argument is non-volatile, the template ctor is chosen.
The thing is, marking a copy ctor deleted where that copy ctor receives a const volatile argument, allows the template member to be called because the copy ctor with non-volatile argment is not generated... this is what I don't understand.
This class never executes the template member but instead calls the generated copy ctor:
1 2 3 4 5 6 7 8 9 10
class C
{
public:
template<typename T>
C(T const&)
{
std::cout << "Template 'copy' constructor\n";
}
C() = default;
};
This class executes the template member when a copy ctor is needed because the copy ctor with volatile argument is marked deleted:
Finally, if we mark the copy ctor without volatile as deleted, then copy ctor is not called because it is deleted...but it does not call the member template either -> it causes a compilation error:
1 2 3 4 5 6 7 8 9 10 11
class C
{
public:
template<typename T>
C(T const&)
{
std::cout << "Template copy constructor\n"; // NEVER CALLED!!
}
C() = default;
C(C const &) = delete;
};
Why is member template never called in this last case?
BTW: I took this from the book C++ Templates The Complete Guide by Josuttis
Why is member template never called in this last case?
because non-template beats template in overload resolution. It's a universal rule, not just for constructors: If you call f(x) and the choices are f(const X&) and template<class T>f(const T&), the best choice is f(const X&).