【问题标题】:Does a template function with different definitions cause undefined behaviour?具有不同定义的模板函数是否会导致未定义的行为?
【发布时间】:2021-08-30 20:18:59
【问题描述】:

0.cc

template <class T>
T get(){
 return 5;
}

int get(){
 return 6;
}

int main(){
 return get<int>();
}

1.cc

template <class T>
T get(){
 return 7;
}
template int get<int>(); // This forces code generation.

使用g++ -Wall 0.cc 1.cc 编译不会导致链接错误,返回的输出是5

问题

1- 即使不使用extern,模板是否默认具有外部链接?

https://en.cppreference.com/w/cpp/language/storage_duration

上面未列出的所有模板的名称(即不是声明为静态的函数模板)。

2- 链接器是否处理多个模板,如inline 函数?即它从许多定义中选择 1 个并且具有不同的定义会导致 UB? https://stackoverflow.com/a/66356946

3- 为什么int get(){} 不会导致链接错误?模板函数和常规函数有不同的符号吗?

【问题讨论】:

  • ODR 已损坏...程序格式错误,无需诊断。
  • 这是三个不同的问题。而且它们并没有太大的关系。
  • @StoryTeller-UnslanderMonica 当我试图理解它是如何以及为什么编译时,它们有点相关。
  • 这不会使它们相关,因为每个问题规则一个问题stackoverflow.com/help/closed-questions

标签: c++ undefined-behavior one-definition-rule


【解决方案1】:

具有不同定义的模板函数会导致未定义的行为吗?

是的。

1- 即使不使用 extern,模板是否默认具有外部链接?

是的,模板函数具有外部链接,除非在匿名命名空间中声明或声明 static 或附加到模块但未导出。

2- 链接器是否将多个模板视为内联函数?

是的。在这方面,函数模板的隐式实例化被视为与内联函数相同。

定义不同会导致UB

是的。从技术上讲,该程序的格式不正确,但它们之间的区别在运行时并不重要。

3- 为什么 int get(){} 不会导致链接错误?

用函数重载函数模板是良构的。

【讨论】:

  • “函数模板是隐式内联的。” 不。允许对它们进行多个定义,但不是因为内联。您可以手动将它们标记为 inline 作为优化器的提示。
  • 问题3,合法吗?这个答案说它可能是:stackoverflow.com/a/16865452
  • @HolyBlackCat 我调整了措辞。
  • 在上面的链接中f是一个常规函数,也是一个模板。答案说这样做是合法的。这也是我的问题 #3。
  • @Dan 我明白了。我以为你的意思是因为两个不同的模板定义。我已经编辑了答案。
【解决方案2】:

具有不同定义的模板函数会导致未定义的行为吗?

Answerr:嗯,是的,如果您以多种方式定义模板,模板的行为确实是未定义的。 应该只有一个定义

BUT
You can use template in some other scope in with different definition

模板是否默认有外部链接,即使不使用外部链接? 答:

Yes,
Templates will cause external linkage in normal circum stances but some exceptions are
Defining them in some outer namespace or using them as an exports.module

链接器是否将多个模板视为内联函数?即它从许多定义中选择 1 个并且具有不同的定义 回答: 显然,模板被视为内联函数

【讨论】:

    猜你喜欢
    • 2017-11-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-07-12
    • 2014-08-11
    • 2016-09-04
    • 1970-01-01
    • 2015-07-30
    相关资源
    最近更新 更多