2008-12-10 4 views
34

Quelqu'un a affirmé sur SO aujourd'hui que vous ne devez jamais utiliser les espaces de noms anonymes dans les fichiers d'en-tête. Normalement, c'est correct, mais il me semble me souvenir qu'une fois quelqu'un m'a dit que l'une des bibliothèques standard utilise des espaces de noms anonymes dans les fichiers d'en-tête pour effectuer une sorte d'initialisation.Utilise des espaces de noms anonymes dans les fichiers d'en-tête

Suis-je bien se souvenant? Quelqu'un peut-il remplir les détails?

+1

Voir cette discussion: [http://stackoverflow.com/questions/357404/anonynous-namespaces](http://stackoverflow.com/questions/357404/anonynous-namespaces) –

+0

qui est le fil où il a obtenu cette information à partir des espaces de noms anonymes dans les en-têtes est mauvais –

+0

Je ne trouve rien dans ce fil à propos de l'utiliser dans les fichiers d'en-tête. Quelqu'un peut-il expliquer pourquoi c'est faux? Et s'applique-t-il toujours en C++ 11? – baruch

Répondre

20

La seule situation dans laquelle un espace de noms sans nom en-tête peut être utile est lorsque vous voulez distribuer le code sous forme de fichiers d'en-tête seulement. Par exemple, un grand sous-ensemble autonome de Boost est purement en-têtes. Le jeton ignore pour les tuples, mentionné dans une autre réponse est un exemple, le _1, _2 etc.

+0

Je pense que vous avez fait un bon point avec cela. –

+0

Vous ne devez pas utiliser d'espace de noms anonyme car ils sont tous regroupés dans l'unité de compilation finale, ce qui peut entraîner des conflits d'espace de noms. Au lieu de cela, utilisez un nom qui, par convention, signifie que les contenus sont des détails d'implémentation. Boost, par exemple, utilise 'detail'. – thehouse

+0

@thehouse Vous semblez avoir mal compris comment Boost utilise les espaces de noms anonymes. 'ignore' et' _1', '_2' etc. sont des symboles publics - ils n'appartiennent pas' detail'. Mais je suis d'accord qu'un espace de noms de détail est normalement le bon choix pour l'équivalent d'un espace de noms anonyme d'une bibliothèque d'en-tête. –

2

Je ne peux voir aucun avantage positif d'utiliser les espaces de noms anonymes en-têtes. La confusion qui peut résulter d'avoir la même déclaration de symbole signifie, en substance, une chose différente dans les unités de compilation qui comprennent cet en-tête serait un moyen garanti d'aller prématurément et douloureusement chauve.

0

S'il s'agit d'une initialisation, il s'agira probablement d'un en-tête iostream (comme istream, ios, etc.).

13

Je ne vois pas de point de mettre un espace de noms anonyme dans un fichier d'en-tête. J'ai les en-têtes standards rassemblés de et les libstdC++, pas trouvé anonyme namespaces en dehors d'un dans l'en-tête tuple (C++ 1x substance):

// A class (and instance) which can be used in 'tie' when an element 
    // of a tuple is not required 
    struct _Swallow_assign 
    { 
    template<class _Tp> 
     _Swallow_assign& 
     operator=(const _Tp&) 
     { return *this; } 
    }; 

    // TODO: Put this in some kind of shared file. 
    namespace 
    { 
    _Swallow_assign ignore; 
    }; // anonymous namespace 

Ceci est donc vous pouvez avoir

std::tie(a, std::ignore, b) = some_tuple; 

Les éléments du some_tuple sont assignés aux variables du côté gauche (voir here), une technique similaire est utilisée pour l'itérateur this. Le deuxième élément est ignoré.

Mais comme on dit, il devrait être mis dans un fichier .cpp et une instance doit être partagée par tous les utilisateurs. Ils ont mis une déclaration dans l'en-tête comme celui-ci alors:

extern _Swallow_assign ignore; 
+0

C++ 1x? Ai-je manqué quelque chose? –

+0

suivant C++ version –

+0

Sutter appelle encore C++ 0x (http://herbsutter.wordpress.com/2008/10/28/september-2008-iso-c-standards-meeting-the-draft-has-landed -et-un-nouveau-convoyeur /). –

4

Je l'ai vu utilisé pour fournir une valeur par défaut pour une variable dans différentes unités de traduction. Mais cela pourrait provoquer un comportement inattendu dans le cas de conflits de noms.

Exemple

a.hpp

namespace 
{ 
    const char name[] = "default"; 
} 
// This macro will hide the anonymous variable "name" 
#define SET_NAME(newname) \ 
static const char name[] = newname; 

b.cpp

#include "a.hpp" 
SET_NAME("file b") // name is "file b" in this translation unit 

c.cpp

#include "a.hpp" 
SET_NAME("file c") // name is "file c" in this translation unit 

d.cpp

#include "a.hpp" 
// name is "default" in this translation unit 

e.cpp

#include "a.hpp" 
static const char name[] = "unintended"; 
// accidently hiding anonymous name 
Questions connexes