1

我的代码中有这样的东西:

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 模板专门用于什么类型,以便可以将它与字符数组一起使用?我尝试const char*了 const、char、* 和 & 的其他组合,但没有任何效果。

请注意,我无法更改DoSomething功能。

另外,如果可能的话,我希望编译器自动推断(或转换)模板类型,而不在DoSomething<smth>()调用中指定它main()

4

4 回答 4

6

a没有 type char*,它有 type char[5],所以主模板被实例化,而不是特化。

如果您手动执行数组到指针的转换,它将使用特化:

char a[5];
char* aptr = a;
DoSomething(a);

如果您不希望将主模板用于char数组,则可以专门化模板:

template <unsigned N> struct A<char[N]> { /* ... */ };
于 2010-08-07T22:09:25.623 回答
1

您可以只遵循编译错误并专门针对char[5].

template <>
struct A<char*>
{
  void Print() { printf("Char*!\n"); }
};

不过,提供这似乎是一个非常奇怪的专业。

如果您想明确指定DoSomething要使用的专业化,那么为什么不这样做呢?

int main()
{
  char a[5];
  DoSomething<char *>(a);
}

当然,你会发现这仍然不能编译,因为DoSomething它需要一个非常量引用,所以你需要一个 type 的左值char *,临时的不行。

int main()
{
  char a[5];
  char *p = a;
  DoSomething<char *>(p);
}
于 2010-08-07T22:12:59.957 回答
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);
}
于 2010-08-07T22:11:12.610 回答
0

另一种强制数组->指针衰减的可能性是创建一个特化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因为非常量引用不能用作引用。

于 2010-08-07T22:23:34.617 回答