Why compiler cares about copy constructor when it doesn't need one?
#include <iostream>
template<typename T>
void print(T);
class Foo {
Foo(const Foo&);
public:
Foo(){}
};
template<>
void print(const Foo& f) {
std::cout << "Foo\n";
}
int main(){
Foo foo;
print(foo);
}
function print
is overloaded to accept const Foo&
but compiler produces the following compilation error:
main.cpp: In function ‘int main()’:
main.cpp:21:14: error: ‘Foo::Foo(const Foo&)’ is private within this context
21 | print(foo);
| ^
main.cpp:7:5: note: declared private here
7 | Foo(const Foo&);
| ^~~
main.cpp:4:12: note: initializing argument 1 of ‘void print(T) [with T = Foo]’
4 | void print(T);
| ^
Why is it so? Obviously we don't need copy constructor, since we passing foo
by reference and we have overload of print
for that.
Your specialization is not used in overload resolution. Overload resolution only synthesizes a signature from the primary template. The specialization is only used when calling the function, and only if the signature matches that which the compiler synthesized by itself. Since the primary takes an argument by value, this is the signature that participates in overload resolution:
void print(Foo); // T = Foo
And it doesn't match the signature you provided in the specialization (T = Foo const&
), so the specialization isn't called. In fact, the only way to call your specialization, as is, is to specify the template argument explicitly:
print<Foo const&>(foo);
The way to proceed is not to specialize, but to overload. You can accomplish that by simply removing the template<>
introducer. The regular overload participates in overload resolution, and will be chosen over the template generated one.