2011-02-07 11 views
11

Nie jestem do końca pewien na ten temat w standardach. Że mam trzy pliki tak:Kwalifikator wbudowany wynika z prototypu lub definicji?

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(); 
} 

Teraz definicja foo zostanie skompilowana do obu jednostek kompilacji foo.o i bar.o. Jeśli rozumiem to poprawnie, posiadanie wbudowanych funkcji pozwoli uniknąć kolizji łącznika. G ++ skompilowany i linki to dobrze, ale z brzękiem ++ 2.8 otrzymuję ten błąd:

/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 

Wydaje się, że szczęk ++ nie widzieć void foo() jako inlined funkcji. Działa to jednak dobrze, gdy dodaję również tekst do definicji.

Czy muszę dodać również w linii do void foo(), aby można go było zobaczyć jako funkcję inline lub czy jest to błąd ++?

+0

Myślę, że masz na myśli "definicję", a nie "deklarację". – Maxpm

+0

Ach, tak, mam tendencję do mieszania tych ...;) – Maister

+0

To interesujące pytanie. –

Odpowiedz

2

C++ 0X projekt N3225 mówi w 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.

Więc dla mnie to wygląda jak gcc ma rację & dzyń źle, ale jest jeszcze (szczupła) szansa, że ​​rzeczy były (są?) różne w C++ 03 ..

+1

C++ 03 jest identyczne, z tym że "odr-used" zostało po prostu "użyte". – aschepler

+0

@Eugen: klauzula 1 również wydaje się całkiem interesująca * Specyfikatory funkcji mogą być używane ** tylko ** w deklaracjach funkcji * (mój nacisk). –

+0

Myślę, że Ben Voigt ma tutaj rację (nie myślałem o tym, kiedy początkowo cytowałem). Definicja jest również deklaracją. Standard mówi: "Deklaracja obiektu jest jednak również definicją, chyba że zawiera zewnętrzny specyfikator i nie ma inicjalizatora." – sstn

0

Musisz użyć inline w obu miejscach.

+4

Nie mogę znaleźć nigdzie w standardzie, który tego wymaga, a w rzeczywistości standard wyraźnie pozwala na przypadek, w którym funkcja składowa deklarowana jest jako "inline" w deklaracji lub definicji, ale nie w obu (funkcja jest 'inline' w ta walizka). –

+0

Może teraz wprowadzam w błąd, ale w standardzie z 1998 roku mówi się: "Może istnieć więcej niż jedna definicja [...] funkcji inline z łączem zewnętrznym, [...] w programie pod warunkiem, że każda definicja pojawia się w innym jednostka tłumaczeniowa, [...] "(sekcja 3.2, klauzula 5) – sstn

+0

7.1.2, klauzula 1 (1998 ponownie ...) mówi:" Specyfikatory funkcji mogą być używane tylko w deklaracjach funkcji. " – sstn

1

Wierzę, że intencją sta Innym sposobem było umożliwienie utworzenia funkcji inline za pomocą co najmniej jednej deklaracji zawierającej specyfikator inline, ale nie było pewności, kiedy było zbyt późno, aby dodać pierwszą deklarację inline. Czy po definicji było za późno, czy po pierwszym telefonie?

Moje rozumowanie jest dwojakie, najpierw przykłady z 7.1.1, chociaż nie są normatywne, a przede wszystkim specyfikatory klasy pamięci, sugerują, że inline nie jest wymagana przy każdej deklaracji.

Po drugie, ten raport o usterce DR 317 z 2001 r. (Przyjęty w 2005 r.), Który dodaje: "Jeśli definicja funkcji pojawia się w jednostce tłumaczeniowej przed pierwszą deklaracją jako inline, program jest źle sformułowany." zdanie. Z rozmowy jasno wynika, że ​​intencją było, aby inline nie było wymagane w przypadku każdej deklaracji, w szczególności w przypadku funkcji członkowskiej zdefiniowanej jawnie jako inline, ale poza treścią klasy, w której oryginalna deklaracja nie miała wyraźnego inline.

(Ten raport o usterce zawiera również moją mantrę, że inline jest "czymś więcej niż podpowiedź".)

Oczywiście, jak tylko funkcję z zewnętrznym łącznikiem jest funkcja inline ze względu na jedną lub więcej zgłoszeń tym inline specyfikatorem w jednej jednostce translacyjnej należy stwierdzić inline we wszystkich jednostkach tłumaczeniowych zgodnie z resztą pkt 7.1.2/4.

W przykładzie w pytaniu uważam, że intencją jest to, że foo jest funkcją inline i że jest to poprawny kod, chociaż normatywny tekst standardu wydaje mi się mniej jasny, niż mógłby być.

4

Szanse są takie, że twój język używa semantyki inline C99. W C99, jeśli jedna z twoich funkcji nie używa "inline" lub zawiera "extern", to definicja jest "zewnętrzną definicją", która może pojawić się tylko raz w programie. Zobacz inline in C99.

W C++ Twój program jest w porządku. W SVN Clang ten błąd został naprawiony i twój program powinien działać dobrze.