c++ - 模板重载导致链接器错误/奇怪的行为

标签 c++ linker language-lawyer overloading function-templates

使用以下最小示例,我在 visual studio 15.8.7(具有标准设置的标准控制台应用程序(仅删除预编译 header ))中的本地系统上出现链接器错误:“错误 LNK1179 文件无效或损坏:COMDAT 重复? ?$f@H@@YAXH@Z'"

#include <cstdio>
template<typename T> void f(T) { printf("1"); }  //#1. T can be deduced
template<typename T> void f(int) { printf("2"); } // #2. T needs to be specified explicitly

int main()
{
    f(8); // a) calls #1
    f<int>(8); // b) calls #2           
}
  • 注释掉调用 a) 或调用 b) 将导致成功链接。独立调用 a) 调用模板定义#1。第二次调用 b) 调用模板定义#2。正如预期的那样。
  • 在 Release模式下构建成功。输出为 11。因此两个调用都调用模板定义 #1。意外。 ODR 违规?
  • 此外,我观察到以下奇怪的行为(在调试设置中):
    1. 我注释掉模板定义#2
    2. 我做了一个完整的重建
    3. 我在模板定义 #2 中回复
    4. 我构建(不是重建,只是构建)
    5. 构建成功
    6. 输出是 11 而不是 12

增量链接做奇怪的事情?

在 wandbox、godbolt 和 coliru 上,我可以使用 gcc 和 clang 编译、链接和运行并获得预期的行为。

要点 3 中描述的观察结果让我认为它与增量链接有关。但也许代码也没有明确定义?学习的时候https://en.cppreference.com/w/cpp/language/function_template我遇到了以下情况:

Two expressions involving template parameters are called functionally equivalent if they are not equivalent, but for any given set of template arguments, the evaluation of the two expressions results in the same value.

If a program contains declarations of function templates that are functionally equivalent but not equivalent, the program is ill-formed; no diagnostic is required.

那么,上面的代码是不是格式错误?我有 ODR 违规吗?或者一切都很好,只是链接器/编译器错误?

编辑:固定点 3。我在定义 #2 或类(class)中回复评论。

更新:新的一天,我想问题已经解决了。今天我无法重现这个问题。我没有更改系统上的任何内容。我刚启动,打开我的项目,它按预期工作。不知道怎么回事。但与学习新的特殊奥术模板重载规则相比,这种方式更好:-P

最佳答案

程序很好。您有两个正在调用的不同 函数。这是编译器和/或链接器错误。

[temp.over.link]导致:

It is possible to overload function templates so that two different function template specializations have the same type.

[ Example:

// translation unit 1:
template<class T>
  void f(T*);
void g(int* p) {
  f(p); // calls f<int>(int*)
}

// translation unit 2:
template<class T>
  void f(T);
void h(int* p) {
  f(p); // calls f<int*>(int*)
}

— end example ]

Such specializations are distinct functions and do not violate the one-definition rule.

你有两个不同的功能模板,句号。关于等价的措辞与模板参数和依赖表达式有关([temp.over.link]/5):

Two expressions involving template parameters are considered equivalent if [...]

int 不涉及模板参数,因此不能认为它等同于 T

关于c++ - 模板重载导致链接器错误/奇怪的行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52838159/

相关文章:

c++ - 特定的 OpenCL 内核在移动设备和 PC 上的表现不同

C++乐透号码生成器

html - 如何制作任何人都可以使用的 CSS 文档?

c++ - 创建一个简单的 'hello world' 并将其与 2 个预编译对象链接在一起

c++ - 将 T 数组别名为 std::complex<T> 数组合法吗?

c++ - 在 C++ 标准中的什么地方可以找到对在全局范围内调用函数的支持?

c++ - 如何建立facebook的抄写员?

c++ - 调整大小后win32重绘

gcc - 静态库中对象的顺序

c++ - 指向释放变量的指针更改地址