2011-10-31 9 views
13

¿Estoy violando la regla de una definición con el siguiente programa?espacios de nombres anónimos y la regla de una definición

// foo.hpp 
#ifndef FOO_HPP_ 
#define FOO_HPP_ 

namespace { 
    inline int foo() { 
     return 1; 
    } 
} 

inline int bar() { 
    return foo(); 
} 
#endif 
//EOF 

y

// m1.cpp 

#include "foo.hpp" 

int m1() { 
    return bar(); 
} 

//EOF 

y

// m2.cpp 

#include "foo.hpp" 

int m2() { 
    return bar(); 
} 

//EOF 

y finalmente

// main.cpp 
#include <iostream> 

int m1(); 
int m2(); 

int main(int, const char* []) 
{ 
    int i = m1(); 
    int j = m2(); 

    std::cout << (i+j) << std::endl; 
    return 0; 
} 

// EOF 

En lo anterior, cabe destacar que foo() se define en un espacio de nombres en el anonimato, por lo que espero que cada uno la unidad de traducción m1.cpp y m2.cpp tendrá su propia versión, por lo que no habrá violación de la ODR. Por otro lado, bar() es simplemente una vieja función en línea que llama a 2 diferentes foo s. Entonces viola la ODR, ¿verdad?

Actualización: Anteriormente he tenido macros en la definición de foo que cambió el valor volvió y cada uno de m1 y m2 definida la macro de forma diferente antes de incluir foo.hpp. (Y con ese ejemplo anterior, g++ produciría un archivo binario que generaría (i+j) con un valor diferente al que cabría esperar). Pero, de hecho, este programa infringe el ODR, incluso si el cuerpo de foo() es idéntico.

+5

Creo que esto ilustra claramente por qué el uso de espacios de nombres anónimos o funciones estáticas en archivos de encabezado trae problemas :) –

Respuesta

7

Esto infringe la ODR. Ver 3.2/5 que está hablando de funciones extern línea (bar):

en cada definición de D, nombres correspondientes, miraron según 3,4, se referirá a una entidad definida dentro de la definición de D, o se referirá a la misma entidad ...

En este caso bar se refiere a dos versiones diferentes de foo, violando la regla.

6

Sí, esta definición de bar() infringe la Regla de una sola definición. Está creando varias definiciones, cada una de las cuales llama a una función diferente llamada foo().

Como dices, sería una violación incluso si todas las versiones de foo() son idénticas, ya que siguen siendo funciones diferentes.

Cuestiones relacionadas