可以重新定义constexpr和内联函数吗? 我正在验证C++引物的声明:

可以重新定义constexpr和内联函数吗? 我正在验证C++引物的声明:,c++,function,inline,constexpr,C++,Function,Inline,Constexpr,取消与其他函数的链接,程序中可能会多次定义内联函数和constexpr函数 我在下面使用了constexprcfunc()的两个定义,期望foo_0()将调用第一个def,而foo_1()将调用第二个def。但是,尝试失败,最终出现编译错误。为什么? constexpr int cfunc(){ 返回42; } int foo_0(){ 返回cfunc(); } constexpr int cfunc(){ 返回42; } int foo_1(){ 返回cfunc(); } int main(i

取消与其他函数的链接,程序中可能会多次定义内联函数和constexpr函数

我在下面使用了constexpr
cfunc()
的两个定义,期望
foo_0()
将调用第一个def,而
foo_1()
将调用第二个def。但是,尝试失败,最终出现编译错误。为什么?

constexpr int cfunc(){
返回42;
}
int foo_0(){
返回cfunc();
}
constexpr int cfunc(){
返回42;
}
int foo_1(){
返回cfunc();
}
int main(int argc,字符**argv){

cout是与其他函数不同,内联函数和constexpr函数可以在程序中多次定义。但是,定义必须完全匹配。

根据标准的理由: 根据§7.1.5/2,施工规范[dcl.施工规范]:

constexpr
函数和
constexpr
构造函数是隐式
inline

根据§3.2/6,一条定义规则[基本定义odr]:

在一个程序中,一个类类型(第9条)、枚举类型(7.2)和具有外部链接的内联函数可以有多个定义,只要每个定义 出现在不同的翻译单元中

根据§7.1.2/4功能规范[dcl.fct.spec]:

内联
功能应在使用odr的每个翻译单元中定义,并且在任何情况下都应具有完全相同的定义

因此,由于
constexpr
函数是隐式
inline
函数,它具有
inline
函数的所有属性。因此,
constexpr
函数可以有多个定义,只要每个定义出现在不同的翻译单元中

程序失败的原因:
在您的情况下,程序失败是因为您违反了此规则。也就是说,您在同一翻译单元(即main.cpp)中重新定义了相同的
constepr
函数。

这是正确的-关于内联函数。这种情况下允许在头中使用内联函数,以便在编译时实现内联(而是在链接时间)

下面的引文根本没有提到
constexpr
,但注意到它们是隐式内联的

正如@R Sahu所解释的,关键是
,前提是每个定义出现在不同的翻译单元中
,而这里的情况并非如此

引用标准§3.2.6:

一个程序中可以有多个带有外部链接(7.1.2)的(…)内联函数(…)的定义,前提是每个定义出现在不同的翻译单元中,并且这些定义满足以下要求。(…)


内联函数可以在程序中定义多次,但在翻译单元中只能定义一次。这意味着它只能在头文件中定义一次。一个翻译单元中不能有多个定义,即使它们是相同的。

只是好奇是否有相关参考?@burrito,§7.1.2[dcl.fct.spec]/4:内联函数应在使用odr的每个翻译单元中定义,并且在每种情况下都应具有完全相同的定义。目前尚不清楚问题中的代码违反了哪种解释。3.2/6:带外部链接的内联函数(7.1.2),但在问题中,
cunfc()的两个定义
匹配但仍然失败。您可以删除所有不是
constexpr
的内容。只有这两个定义相关。
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;

}