C++ does not instantiate templates with, say T = Hoge&
.
A minimal example:
hoge.h
:
#include<cstdio>
class Hoge
{
public:
Hoge()
: hoge(0)
{
}
~Hoge()
{
}
int hoge;
void print() { printf("%d\n", hoge); }
};
template<typename T>
void f(T a);
hoge.cpp
:
#include "hoge.h"
template<typename T>
void f(T a)
{
a.print();
}
template void f<Hoge &>(Hoge &a);
main.cpp
:
#include "hoge.h"
int main(void)
{
Hoge h;
f(h);
return 0;
}
I compiled these with: g++ -std=c++11 main.cpp hoge.cpp
. But it gives a linker error:
Undefined symbols for architecture x86_64:
"void f<Hoge>(Hoge)", referenced from:
_main in aa-e35088.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
Next, I changed f(h)
in main.cpp
to f<Hoge &>
, and the error disappeared.
Why is f<Hoge &>(Hoge &)
not called in the first case?
For this case, I can avoid errors by typing f<Hoge &>
every time. But, when it comes to overloaded operators, it cannot be done.
Please tell me how to solve this error.
The compiler will try to deduce the simplest template T
possible. Here, T=Hoge
is fine, so the compiler doesn't try more elaborated forms.
You can clearly state your intent though. Try the following:
template<typename T>
void f(T& a);
T
will still be deduced as Hoge
, but your function f
will get a reference.
This allows the reader to clearly see that directly in f
prototype.
When it comes to template argument deduction, there is a lot of rules occurring under the compiler hood. When I state the compiler deduce the simplest T possible, I'm really cutting corners. Here is a fiable source: cppreference
You can instantiate the function with a reference type just the way you did. However, the compiler will not deduce the template argument as a reference type. You can verify that you can instantiate the function template OK by not having the compiler deduce the argument but rather specifying the argument:
f<Hoge&>(h);
If you want to get a reference type deduced you'll need to use a forwarding reference as an argument of your function template:
template <typename T>
void f(T&& a);
When using a forwarding reference as a template argument and passing an Hoge
argument, the argument is deduced according to the value category of argument:
Hoge h;
Hoge const c;
f(h); // T becomes Hoge&
f(c); // T becomes Hoge const&
f(Hoge()); // T becomes Hoge
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With