我刚刚读到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?
答案 0 :(得分:3)
我刚刚读到constexpr和内联函数遵循单定义规则,但它们的定义必须相同。
这是参考不同翻译单元中的内联函数。在您的示例中,它们都在同一个翻译单元中。
draft C++ standard 3.2
一个定义规则 [basic.def.odr] 中包含以下内容:
类类型(第9条),枚举类型(7.2),内联函数可以有多个定义 外部链接(7.1.2),类模板(第14章),非静态函数模板(14.5.6),静态数据成员 类模板(14.5.1.3),类模板的成员函数(14.5.1.1)或模板特化 其中一些模板参数未指定(14.7,14.5.5),在程序中提供了每个定义 出现在不同的翻译单元中,并且定义满足以下要求。特定 这样一个名为D的实体在多个翻译单元中定义,然后
并包含以下项目符号:
- D的每个定义应由相同的令牌序列组成;和
答案 1 :(得分:3)
您正在一个翻译单元中重复定义功能。这总是被禁止的:
任何翻译单元都不得包含任何变量,函数,类类型,枚举的多个定义 类型或模板。 (C ++ 11 3.2 / 1)
对于inline
函数,允许在多个转换单元中以完全相同的方式定义相同的函数(读取:.cpp文件)。实际上,必须在每个翻译单元中定义它(通常通过在头文件中定义它来完成):
内联函数应在每个使用它的翻译单元中定义。 (C ++ 11 3.2 / 3)
对于具有外部链接(非静态)函数的“正常”(非内联,非constexpr,非模板等)函数,通常(不需要诊断)会导致链接器错误。
每个程序都应该包含每个非内联函数或odr使用的变量的一个定义 在该计划中;无需诊断。 (C ++ 11 3.2 / 3)
总结一下:
inline
函数class
类型和template
s static
class template
。答案 2 :(得分:1)
如果你有:
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
函数的两个版本不相同。