我的代码中有这样的内容:
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);
}
这会产生以下链接器错误:
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)
我应该将A模板专门用于什么类型,以便我可以将它与char-array一起使用?我尝试了const char*
以及const,char,*和&amp;的其他组合,但没有任何作用。
请注意,我无法更改DoSomething
功能。
此外,如果可能,我希望编译器自动推导(或转换)模板类型,而不在DoSomething<smth>()
的{{1}}调用中指定它。
答案 0 :(得分:5)
a
没有类型char*
,类型为char[5]
,因此主模板已实例化,而不是专业化。
如果手动执行数组到指针的转换,它将使用特化:
char a[5];
char* aptr = a;
DoSomething(a);
如果您不希望主模板用于char
数组,则可以专门化模板:
template <unsigned N> struct A<char[N]> { /* ... */ };
答案 1 :(得分:1)
您可以按照编译错误专门研究char[5]
。
template <>
struct A<char*>
{
void Print() { printf("Char*!\n"); }
};
但是,这似乎是一个非常奇怪的专业化。
如果您想明确指定要使用的DoSomething
专精,那么为什么不这样做呢?
int main()
{
char a[5];
DoSomething<char *>(a);
}
当然,您会发现这仍然无法编译,因为DoSomething
采用非const引用,因此您需要一个类型为char *
的左值,暂时不会这样做。< / p>
int main()
{
char a[5];
char *p = a;
DoSomething<char *>(p);
}
答案 2 :(得分:0)
char a[5];
char* aPointer = &a[0];
DoSomething(aPointer);
这会将char *传递给DoSomething。
以下是您完整的示例代码,经过修改后可以正确执行此操作:
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);
}
答案 3 :(得分:0)
强制array-&gt;指针衰减的另一种可能性是创建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);
}
(您应该设置DoSomething
const
的参数,因为如果将数组传递给它,则nonconst引用不能作为引用。