在内联和 constexpr 功能的情况下"obey ODR"意味着什么?



我刚刚读到constexpr和内联函数遵循一个定义规则,但它们的定义必须相同。所以我尝试了一下:

inline void foo() {
    return;
}
inline void foo() {
    return;
}
int main() {
    foo();
};

错误:"void foo()"的重新定义,

constexpr int foo() {
    return 1;
}
constexpr int foo() {
    return 1;
}
int main() {
    constexpr x = foo();
}; 

错误:"constexpr int foo()"的重新定义

那么,constexpr和内联函数究竟意味着什么可以服从ODR呢?

我刚刚读到constexpr和内联函数遵循一个定义规则,但它们的定义必须相同。

这是对不同翻译单元中的内联函数的引用。在您的示例中,它们都在同一个翻译单元中。

这在C++标准草案3.2一个定义规则[basic.def.odr]中有介绍,其中写道:

类类型(第9条)、枚举类型(7.2)、内联函数可以有多个定义外部链接(7.1.2)、类模板(第14条)、非静态函数模板(14.5.6)、静态数据成员类模板的成员函数(14.5.1.1),或如果每个定义出现在不同的翻译单元中,前提是定义满足以下要求。鉴于这样一个名为D的实体在多个翻译单元中定义,然后是

包括以下项目符号:

  • D的每个定义应由相同的令牌序列组成;以及

在一个翻译单元中重复定义函数。这总是被禁止的:

任何翻译单元都不得包含任何变量、函数、类类型、枚举的多个定义类型或模板。(C++11 3.2/1)

对于inline函数,您可以在多个转换单元(读取:.cpp文件)中以完全相同的方式定义相同的函数。事实上,必须在每个翻译单元中定义它(通常通过在头文件中定义它来完成):

内联函数应在其使用的每个翻译单元中定义。(C++11 3.2/3)

对于具有外部链接(非静态)函数的"正常"(非内联、非constexpr、非模板等)函数,这通常(不需要诊断)会导致链接器错误。

每个程序应包含odr使用的每个非内联函数或变量的一个定义在该项目中;无需诊断。(C++11 3.2/3)

综上所述:

  • 永远不要在一个翻译单元中多次定义任何内容(它是.cpp文件和所有直接或间接包含的头)
  • 您可以将一定数量的内容放入头文件中,这些内容将被包含在几个不同的翻译单元中一次,例如:
    • inline功能
    • class型和templates
    • CCD_ 6是CCD_

如果您有:

file1.cpp:

inline void foo() { std::cout << "Came to foo in file1.cpp" << std::endl; }

file2.cpp:

inline void foo() { std::cout << "Came to foo in file2.cpp" << std::endl; }

并且在可执行文件中将这些文件链接在一起,则违反了one-definition-rule,因为inline函数的两个版本不相同。

相关内容

  • 没有找到相关文章

最新更新