不同翻译单元中内联函数的不同实现

R S*_*ahu 1 c++ inline language-lawyer

C++标准说明了ODR,因为它适用于内联函数(强调我的):

3.2一个定义规则

3每个程序应包含该程序中每个非内联函数或变量的一个定义; 无需诊断.该定义可以在程序中明确显示,可以在标准或用户定义的库中找到,或者(在适当的时候)隐式定义(见12.1,12.4和12.8).内联函数应在每个使用它的翻译单元中定义.

它没有说明内联函数是否可以在不同的翻译单元中具有不同的实现.我尝试了以下方法:

test-1.cc

#include <iostream> 
inline std::ostream& foo(std::ostream& os)
{
   return os << "Foo_1";
}

void test_1()
{
   foo(std::cout) << std::endl;
}
Run Code Online (Sandbox Code Playgroud)

test-2.cc

#include <iostream> 
inline std::ostream& foo(std::ostream& os)
{
   return os << "Foo_2";
}

void test_2()
{
   foo(std::cout) << std::endl;
}
Run Code Online (Sandbox Code Playgroud)

main.cc

extern void test_1();
extern void test_2();

int main()
{
   test_1();
   test_2();
   return 0;
}
Run Code Online (Sandbox Code Playgroud)

我期待看到以下输出:

Foo_1
Foo_2
Run Code Online (Sandbox Code Playgroud)

相反,我看到:

Foo_1
Foo_1
Run Code Online (Sandbox Code Playgroud)

我用它来测试它g++ 4.7.3.

g ++在选择其中一个内联实现时是否正确?是否不可能在不同的翻译单元中提供内联函数的不同实现?

dom*_*om0 9

ISO C++2003§3.2第5段说

类类型(第9节),枚举类型(7.2),带有外部链接的内联函数(7.1.2),类模板(第14节),非静态函数模板(14.5.5)可以有多个定义,类模板的静态数据成员(14.5.1.3),类模板的成员函数(14.5.1.1),或模板专用,在提供的程序中未指定某些模板参数(14.7,14.5.4)每个定义出现在不同的翻译单元中,并且定义满足以下要求.鉴于这样一个名为D的实体在多个翻译单元中定义,那么

  • D的每个定义应由相同的令牌序列组成
  • (更多要求如下)

...

如果D的定义不满足这些要求,那么行为是不确定的.

所以,不,非等同的定义是非法的.由于行为未定义,编译器几乎可以自由地做任何事情,包括选择他最喜欢的实现并忽略其他实现.