"unresolved external symbol" on template specialization for array of char
I have something like this in my code:
template <typename T>
struct A
{
void Print();
};
template <>
struct A<char*>
{
void Print() { printf("Char*!\n"); }
};
template <typename T>
void DoSomething(T& lol)
{
A<T> a;
a.Print();
}
int main()
{
char a[5];
DoSomething(a);
}
And this produces the following linker error:
error LNK2019: unresolved external symbol "public: void __thiscall A<char [5]>::Print(void)" (?Print@?$A@$$BY04D@@QAEXXZ) referenced in function "void __cdecl DoSomething<char [5]>(char const (&)[5])" (??$DoSomething@$$BY04D@@YAXAAY04$$CBD@Z)
What type should I specialize the A template for, so that I can use it with a array-of-char? I tried const char*
and other combinations of const, char, * and &, and nothing works.
Note that I cannot change the DoSomething
function.
Also, if possible, I would like the开发者_运维技巧 compiler to automatically deduce (or convert) the template type without specifying it in the DoSomething<smth>()
call in main()
.
a
does not have type char*
, it has type char[5]
, so the primary template is instantiated, not the specialization.
If you manually perform the array-to-pointer conversion, it will use the specialization:
char a[5];
char* aptr = a;
DoSomething(a);
If you don't want the primary template to be used for a char
array, you can specialize the template:
template <unsigned N> struct A<char[N]> { /* ... */ };
You could just follow the compile error and specialize for char[5]
.
template <>
struct A<char*>
{
void Print() { printf("Char*!\n"); }
};
It seems like a very strange specialization to provide, though.
If you want to explicitly specify a which specialization of DoSomething
to use, then why not do exactly that?
int main()
{
char a[5];
DoSomething<char *>(a);
}
Of course, you'll find that this still doesn't compile as DoSomething
takes a non-const reference so you need an lvalue of type char *
, a temporary won't do.
int main()
{
char a[5];
char *p = a;
DoSomething<char *>(p);
}
char a[5];
char* aPointer = &a[0];
DoSomething(aPointer);
This will pass a char* to DoSomething.
Here is your complete sample code, modified to do this correctly:
template <typename T>
struct A
{
void Print();
};
template <>
struct A<char*>
{
void Print() { printf("Char*!\n"); }
};
template <typename T>
void DoSomething(T& lol)
{
A<T> a;
a.Print();
}
int main()
{
char a[5];
char* aPointer = &a[0];
DoSomething(aPointer);
}
Another possibility to force array->pointer decay would be creating a specialization of DoSomething
:
template <typename T>
void DoSomething(const T& lol)
{
A<T> a;
a.Print();
}
template <class T, unsigned N>
void DoSomething(T(& x)[N])
{
DoSomething(x+0);
}
(you should make the parameter of DoSomething
const
since nonconst reference cannot work as a reference if you pass arrays to it.
精彩评论