内联限定符源于原型或定义?

时间:2011-02-07 18:21:48

标签: c++ gcc clang

我对标准中的这一点不太确定。说我有三个这样的文件:

foo.h中

#include <iostream>

inline void foo();

void foo()
{
   std::cout << "Foo" << std::endl;
}

Foo.cpp中:

#include "foo.h"

void baz();

int main()
{
   baz();
   foo();
}

bar.cpp

#include "foo.h"

void baz()
{
   foo();
}

现在,foo的定义将被编译到编译单元foo.o和bar.o.如果我理解正确,内联函数将避免链接器冲突。 G ++编译并链接这很好,但是使用clang ++ 2.8我得到了这个错误:

/tmp/cc-7RdmYP.o: In function `foo()':
bar.cpp:(.text+0x50): multiple definition of `foo()'
/tmp/cc-LW3id3.o:foo.cpp:(.text+0x50): first defined here
collect2: ld returned 1 exit status

似乎clang ++没有将void foo()视为内联函数。但是,当我向定义添加内联时,它确实可以正常工作。

我是否必须在此处添加内联到void foo()以使其被视为内联函数,或者这是一个clang ++错误?

4 个答案:

答案 0 :(得分:4)

可能的是你的clang使用C99内联语义。在C99中,如果您的某个函数不使用“内联”或包含“extern”,则该定义是“外部定义”,它只能在程序中出现一次。请参阅inline in C99

在C ++中,你的程序很好。在Clang SVN中,此错误已得到修复,您的程序应该可以正常工作。

答案 1 :(得分:2)

C ++ 0X草案N3225在7.1.2 Function specifiers中说:

  • clause 2: A function declaration with an inline specifier declares an inline function
  • clause 4: An inline function shall be defined in every translation unit in which it is odr-used and shall have exactly the same definition in every case.

所以,对我来说,看起来gcc是对的&amp; clang错了,但是C ++ 03中的东西仍然存在(微小的)不同的可能性。

答案 2 :(得分:1)

我认为标准的意图一直是允许通过至少一个包含inline说明符的声明来inline创建一个函数,但是对于它何时也存在一些不确定性迟到添加第一个inline声明。是在定义太晚之后,还是在第一次通话之后?

我的理由是双重的,首先是7.1.1中的示例,尽管是非规范性的,主要是关于存储类说明符,但建议每个声明都不需要inline

其次,这个缺陷报告DR 317来自2001年(2005年投票),其中增加了“如果函数的定义在第一次声明为内联之前出现在翻译单元中,那么该程序就是格式错误。”句子。从对话中可以清楚地看出,每个声明都不需要inline,特别是在成员函数明确定义inline的情况下,但在原始声明没有的类主体之外没有明确的inline

(该缺陷报告还包含我的口头禅inline“不仅仅是一个提示”。)

当然,一旦具有外部链接的函数是内联函数,由于一个或多个声明包括一个翻译单元中的inline说明符,它必须被声明为{{1根据第7.1.2 / 4段其余部分的所有翻译单位。

在问题的例子中,我认为意图是inline是一个内联函数,并且它是有效的代码,尽管标准的规范性文本在我看来并不那么明确。

答案 3 :(得分:0)

你必须在两个地方都使用inline