2011-10-31 2 views
13

Est-ce que je viole la règle de définition unique avec le programme suivant?namespaces anonymes et la règle de définition unique

// foo.hpp 
#ifndef FOO_HPP_ 
#define FOO_HPP_ 

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

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

et

// m1.cpp 

#include "foo.hpp" 

int m1() { 
    return bar(); 
} 

//EOF 

et

// m2.cpp 

#include "foo.hpp" 

int m2() { 
    return bar(); 
} 

//EOF 

et enfin

// 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 

Dans ce qui précède, notez que foo() est définie dans un espace de noms anonyme, donc je pense que chaque unité de traduction m1.cpp et m2.cpp aura sa propre version, donc il n'y a pas de violation de l'ODR. D'autre part, bar() est juste une vieille fonction en ligne simple qui arrive à appeler 2 différents foo s. Donc, cela viole l'ODR, n'est-ce pas?

Mise à jour: Auparavant, j'avais des macros dans la définition de foo qui a changé la valeur il est revenu et chacun défini la macro différemment m1 et m2 avant d'inclure foo.hpp. (Et avec cet exemple précédent, g++ produirait un binaire qui produirait (i+j) avec une valeur autre que celle que vous attendez.) Mais en fait ce programme viole l'ODR même si le corps de foo() est identique.

+5

Je pense que cela illustre clairement pourquoi l'utilisation d'espaces de noms anonymes ou de fonctions statiques dans les fichiers d'en-tête pose des problèmes :) –

Répondre

7

Ceci enfreint le protocole ODR. Voir 3.2/5 qui parle de fonctions inline externat (bar):

dans chaque définition de D, les noms correspondants, leva les yeux selon 3.4, se réfère à une entité définie dans la définition de D, ou se rapportent à la même entité ...

Dans ce cas bar fait référence à deux versions différentes de foo, violant ainsi la règle.

6

Oui, cette définition de bar() enfreint la règle de définition unique. Vous créez plusieurs définitions, dont chacune appelle une fonction différente appelée foo(). Comme vous le dites, ce serait une violation même si toutes les versions de foo() sont identiques, car elles sont encore différentes fonctions.