2011-02-07 11 views
11

No estoy seguro de esto en los estándares. Decir que tengo tres archivos como este:calificador en línea se deriva de prototipo o definición?

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

Ahora, la definición de foo se compilará en ambas unidades de compilación foo.o y bar.o. Si lo entiendo correctamente, tener funciones inline evitará la colisión del enlazador. G ++ compila y vincula esta muy bien, pero con ruido metálico ++ 2.8 me sale este error:

/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 

Parece que tañido ++ no ve void foo() como una función inline. Sin embargo, funciona bien cuando agrego en línea a la definición también.

¿Debo agregar inline al void foo() también aquí para que se lo vea como una función inline, o es esto un error de clang ++?

+0

Creo que te refieres a "definición", no "declaración". – Maxpm

+0

Ah, sí, tiendo a mezclar esos ...;) – Maister

+0

Esta es una pregunta interesante. –

Respuesta

2

C++ 0X proyecto N3225 dice en 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.

Así que, para mí, parece que gcc es correcta & sonido metálico mal, pero todavía hay una (delgado) posibilidad de que las cosas fueran (¿son?) diferentes en C++ 03 ..

+1

La redacción de C++ 03 es idéntica, excepto que "odr-used" simplemente se "usó". – aschepler

+0

@Eugen: la cláusula 1 parece bastante interesante también * Los especificadores de funciones se pueden usar ** solo ** en declaraciones de funciones * (énfasis mío). –

+0

Creo que Ben Voigt está en lo correcto aquí (no lo pensé al citar inicialmente). Una definición es también una declaración. El estándar dice: 'Una declaración de objeto, sin embargo, también es una definición a menos que contenga el especificador externo y no tenga un inicializador. – sstn

0

Tienes que usar inline en ambos lugares.

+4

No puedo encontrar nada en el estándar que requiera esto, y de hecho, el estándar permite específicamente el caso donde una función miembro se declara 'en línea' en declaración o definición, pero no ambas (la función es' en línea' en Ese caso). –

+0

Tal vez estoy confundiendo las cosas ahora, pero la norma de 1998 dice "Puede haber más de una definición de [...] función en línea con enlace externo [...] en un programa, siempre que cada definición aparezca en un formato diferente". unidad de traducción, [...] "(sección 3.2, cláusula 5) – sstn

+0

7.1.2, cláusula 1 (1998 nuevamente ...) dice:" Los especificadores de función solo se pueden usar en declaraciones de funciones ". – sstn

1

Creo que la intención del sta ndard siempre ha permitido permitir que se realice una función inline al tener al menos una declaración que incluye el especificador inline, pero había cierta incertidumbre acerca de cuándo era demasiado tarde para agregar la primera declaración inline. ¿Fue después de la definición demasiado tarde o después de la primera llamada?

Mi razonamiento para esto es doble, primero los ejemplos en 7.1.1, aunque no normativos y principalmente sobre los especificadores de clase de almacenamiento, sugieren que inline no se requiere en cada declaración.

En segundo lugar este informe de defectos DR 317 de 2001 (votado en 2005) que agrega "Si la definición de una función aparece en una unidad de traducción antes de su primera declaración como en línea, el programa está mal formado". frase. De la conversación se desprende claramente que no se requiere inline en cada declaración, específicamente en el caso de una función miembro explícitamente definida inline pero fuera del cuerpo de la clase donde la declaración original no tenía un inline explícito.

(Ese informe de defectos también contiene mi mantra que inline es "más que una pista".)

Por supuesto, tan pronto como una función con enlace externo es una función línea debido a una o más declaraciones, incluyendo la inline especificador en una unidad de traducción se debe declarar inline en todas las unidades de traducción de acuerdo con el resto de párrafo 7.1.2/4.

En el ejemplo de la pregunta, creo que la intención es que foo sea una función en línea y que sea un código válido aunque el texto normativo de la norma me parece menos claro de lo que podría ser.

4

Las probabilidades son que su clang utiliza la semántica en línea C99. En C99, si una de sus funciones no utiliza "en línea" o incluye "extern", entonces la definición es una "definición externa", que solo puede aparecer una vez en el programa. Ver inline in C99.

En C++, su programa está bien. En Clang SVN, este error ha sido reparado y tu programa debería funcionar bien.

Cuestiones relacionadas