Встроенный классификатор происходит от прототипа или определения? - PullRequest
11 голосов
/ 07 февраля 2011

Я не совсем уверен в этом в стандартах.Допустим, у меня есть три таких файла:

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() как встроенную функцию.Тем не менее, он работает нормально, когда я добавляю inline к определению.

Должен ли я также добавить inline к void foo(), чтобы он рассматривался как встроенная функция, или это ошибка clang ++?

Ответы [ 4 ]

4 голосов
/ 09 февраля 2011

Скорее всего, ваш кланг использует встроенную семантику C99. В C99, если одна из ваших функций не использует «inline» или включает «extern», тогда определение является «внешним определением», которое может появиться в программе только один раз. См. встроенный в C99 .

В C ++ ваша программа в порядке. В Clang SVN эта ошибка была исправлена, и ваша программа должна работать нормально.

2 голосов
/ 07 февраля 2011

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 верен и лягает неправильно, но все еще есть (малый) шанс, что в С ++ все было (есть?) иначе ..

1 голос
/ 08 февраля 2011

Я считаю, что цель стандарта всегда состояла в том, чтобы сделать функцию inline возможной, имея хотя бы одно объявление, включающее спецификатор inline, но существовала некоторая неопределенность относительно того, когда было слишком поздно добавлятьпервая inline декларация.Было ли это после определения слишком поздно или после первого вызова?

Я рассуждаю по этому поводу в два раза, сначала примеры в 7.1.1, хотя и ненормативные и, в основном, о спецификаторах классов хранения, предполагают, что inline не требуется в каждом объявлении.

Во-вторых, этот отчет о дефектах DR 317 от 2001 г. (проголосовал в 2005 г.), в котором добавлено «Если определение функции появляется в переводческой единицедо ее первого объявления в качестве встроенной, программа является плохо сформированной ".предложение.Из разговора ясно, что предполагалось, что inline не требуется для каждого объявления, особенно в случае функции-члена, определенной явно inline, но вне тела класса, где исходное объявление не имелоявный inline.

(В этом отчете о дефектах также содержится моя мантра о том, что inline «больше, чем подсказка».)

Конечно, как только функция с внешней связью встроенная функция из-за одного или нескольких объявлений, включающих спецификатор inline в одной единице перевода, она должна быть объявлена ​​inline во всех единицах перевода в соответствии с остальной частью параграфа 7.1.2 / 4.

В примере, приведенном в вопросе, я считаю, что намерение состоит в том, что foo является встроенной функцией и является допустимым кодом, хотя мне кажется, что нормативный текст стандарта менее ясен, чем мог бы быть.

0 голосов
/ 07 февраля 2011

Вы должны использовать inline в обоих местах.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...