2011-02-07 16 views
11

Non sono abbastanza sicuro di questo negli standard. Dire che ho tre file come questo:Il qualificatore in linea deriva dal prototipo o dalla definizione?

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

Ora, la definizione di foo verrà compilata in entrambe le unità di compilazione foo.o e bar.o. Se ho capito bene, avere funzioni integrate eviterà la collizione del linker. G ++ compilato e collegamenti questo bene, ma con clang ++ 2.8 ottengo questo errore:

/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 

Sembra che clang ++ non vede void foo() come funzione inline. Tuttavia, funziona bene quando aggiungo anche alla definizione.

Devo aggiungere in linea a void foo() anche qui per averlo visto come una funzione inline, o si tratta di un bug di clang ++?

+0

Penso che tu intenda "definizione", non "dichiarazione". – Maxpm

+0

Ah, sì, tendo a mescolare quelli ...;) – Maister

+0

Questa è una domanda interessante. –

risposta

2

C++ 0X progetto N3225 dice nel 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.

Quindi, per me, sembra che gcc è giusto & clang sbagliato, ma c'è ancora un (sottile) possibilità che le cose fossero (sono?) diverse in C++ 03 ..

+1

La formulazione C++ 03 è identica tranne che "odr-used" è stato semplicemente "usato". – aschepler

+0

@Eugen: anche la clausola 1 sembra molto interessante * Gli identificatori di funzioni possono essere usati ** solo ** nelle dichiarazioni di funzione * (il mio accento). –

+0

Penso che Ben Voigt sia corretto qui (non ci ho pensato quando ho citato inizialmente). Una definizione è anche una dichiarazione. Lo standard dice: 'Una dichiarazione di oggetto, tuttavia, è anche una definizione a meno che non contenga lo specificatore esterno e non abbia inizializzatore. – sstn

0

Devi usare inline in entrambi i posti.

+4

Non riesco a trovarmi da nessuna parte nello standard che lo richiede, e in effetti lo standard consente specificamente il caso in cui una funzione membro viene dichiarata "in linea" alla dichiarazione o definizione, ma non entrambe (la funzione è 'inline' in questo caso). –

+0

Forse ora sto confondendo le cose, ma lo standard del 1998 dice "Ci può essere più di una definizione di [...], funzione inline con collegamento esterno, [...] in un programma a condizione che ogni definizione appaia in un altro unità di traduzione, [...] "(sezione 3.2, clausola 5) – sstn

+0

7.1.2, clausola 1 (1998 di nuovo ...) dice:" Gli identificatori di funzione possono essere utilizzati solo nelle dichiarazioni di funzione. " – sstn

1

Credo che l'intenzione della sta ndard è sempre stato quello di consentire una funzione da effettuare inline con almeno una dichiarazione incluso l'identificatore inline ma c'era qualche incertezza su quando era troppo tardi per aggiungere la prima dichiarazione inline. Era dopo la definizione troppo tardi, o dopo la prima chiamata?

Il mio ragionamento per questo è due volte, in primo luogo gli esempi in 7.1.1, sebbene non normativo e principalmente sugli specificatori di classe di memoria, suggeriscono che inline non è richiesto su ogni dichiarazione.

In secondo luogo questo rapporto di difetto DR 317 del 2001 (votato nel 2005) che aggiunge "Se la definizione di una funzione viene visualizzata in un'unità di traduzione prima della prima dichiarazione come inline, il programma è mal formato". condanna, frase. È chiaro dalla conversazione che era intuito che inline non è richiesto su ogni dichiarazione, in particolare nel caso di una funzione membro definita esplicitamente inline ma al di fuori del corpo della classe in cui la dichiarazione originale non aveva un esplicito inline.

(Il rapporto sui difetti contiene anche il mio mantra che inline è "più di un suggerimento".)

Naturalmente, non appena una funzione con linkage esterno è una funzione linea causa di una o più dichiarazioni compreso il inline specificatore in un'unità di traduzione si deve dichiarare inline in tutte le unità di traduzione secondo il resto paragrafo 7.1.2/4.

Nell'esempio della domanda credo che l'intenzione sia che foo è una funzione inline e che è un codice valido anche se il testo normativo dello standard mi sembra meno chiaro di quanto potrebbe essere.

4

Le probabilità sono che il vostro clangore usi la semantica in linea C99. In C99, se una delle tue funzioni non usa "in linea" o include "extern", la definizione è una "definizione esterna", che può apparire solo una volta nel programma. Vedi inline in C99.

In C++, il programma è a posto. In Clang SVN, questo bug è stato corretto e il tuo programma dovrebbe funzionare correttamente.

Problemi correlati