我正在验证关于C ++ Primer的声明:
Unlinke其他函数,inline和constexpr函数可以在程序中多次定义。
我在下面使用了一个constexpr cfunc()
的两个定义,期望foo_0()
将调用第一个def而foo_1()
将调用第二个def。但是,尝试失败并出现编译错误(最后)。为什么呢?
constexpr int cfunc(){
return 42;
}
int foo_0(){
return cfunc();
}
constexpr int cfunc(){
return 42;
}
int foo_1(){
return cfunc();
}
int main(int argc, char **argv) {
cout << foo_0() << endl;
cout << foo_1() << endl;
/* testconstexprfunc2.cpp:24:15: error: redefinition of ‘constexpr int cfunc()’ */
/* testconstexprfunc2.cpp:16:15: error: ‘constexpr int cfunc()’ previously defined here */
return 0;
}
答案 0 :(得分:9)
是的,与其他功能不同,内联和constexpr功能可以在程序中多次定义。 但是,定义必须完全匹配。
来自§7.1.5/ 2 constexpr规范[dcl.constexpr]:
constexpr
函数和constexpr
构造函数隐式inline
。
来自§3.2/ 6一个定义规则[basic.def.odr]:
在一个程序中,每个定义都可以有多个类类型(第9条),枚举类型(7.2),
inline
函数与外部链接...的定义 出现在一个不同的翻译单元......
来自§7.1.2/ 4功能指标[dcl.fct.spec]:
inline
函数应在每个使用过的翻译单元中定义,并且在每种情况下都应具有完全相同的定义。
因此,由于constexpr
函数隐式inline
,因此它具有inline
函数的所有属性。因此, constexpr
函数可以有多个定义,前提是每个定义出现在不同的翻译单元。
在您的情况下,程序失败,因为您违反了此规则。也就是说,您在同一个翻译单元(即main.cpp)中重新定义了相同的constexpr
函数。
答案 1 :(得分:4)
内联函数可以在程序中多次定义,但在翻译单元中只能定义一次。这意味着它只能在头文件中定义一次。即使翻译单元相同,您也无法在翻译单元中定义多个定义。
答案 2 :(得分:2)
确实如此 - 关于内联函数。这是允许在头文件中使用内联函数的情况,以便在编译时(而不是在链接时)进行内联。
以下引文根本没有提到constexpr
,但如上所述,它们是隐式内联的。
正如@R Sahu所解释的那样,关键是provided that each definition appears in a different translation unit
,而这里并非如此。
引用标准,§3.2.6:
如果每个定义出现在一个不同的翻译单元中,那么(...)内联函数的定义可能不止一个与外部链接(7.1.2)(...)的内联函数,并且定义满足以下要求。 (...)