“未解析的外部符号”关于 char 数组的模板专业化

发布于 2024-09-13 04:24:38 字数 892 浏览 5 评论 0原文

我的代码中有这样的内容:

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 函数。

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

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().

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

梦屿孤独相伴 2024-09-20 04:24:38

a 没有类型 char*,它具有类型 char[5],因此实例化的是主模板,而不是特化。

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

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

如果您不希望主模板用于 char 数组,您可以特化该模板:

template <unsigned N> struct A<char[N]> { /* ... */ };

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]> { /* ... */ };
ゝ偶尔ゞ 2024-09-20 04:24:38

您可以只关注编译错误并专门针对 char[5]

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

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

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

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

当然,您会发现这仍然无法编译,因为 DoSomething 采用非常量引用,因此您需要一个 char * 类型的左值,临时不会'不做。

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

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);
}
月朦胧 2024-09-20 04:24:38
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);
}
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);
}
梦归所梦 2024-09-20 04:24:38

强制数组->指针衰减的另一种可能性是创建 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,因为非 const如果将数组传递给引用,则引用不能用作引用。

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文