Utilisations des espaces de noms anonymes dans les fichiers d’en-tête

Quelqu’un a affirmé aujourd’hui sur SO que vous ne devriez jamais utiliser d’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 qu’une des bibliothèques standard utilisait des espaces de noms anonymes dans les fichiers d’en-tête pour effectuer une sorte d’initialisation.

Est-ce que je me souviens correctement? Quelqu’un peut-il remplir les détails?

La seule situation dans laquelle un espace de nom sans nom dans l’en-tête peut être utile est lorsque vous souhaitez dissortingbuer le code sous forme de fichiers d’en-tête uniquement. Par exemple, un grand sous-ensemble autonome de Boost est constitué uniquement d’en-têtes.

Le jeton ignore pour les n-uplets, mentionné dans une autre réponse, en est un exemple; les espaces réservés de liaison _1 , _2 etc. en sont d’autres.

Je ne vois aucune raison de mettre un espace de noms anonyme dans un fichier d’en-tête. J’ai rencontré les en-têtes standard et libstdc ++, je n’ai trouvé aucun espace de nom anonyme, à l’exception de l’un dans l’en-tête du tuple (éléments C ++ 1x):

  // A class (and instance) which can be used in 'tie' when an element // of a tuple is not required struct _Swallow_assign { template _Swallow_assign& operator=(const _Tp&) { return *this; } }; // TODO: Put this in some kind of shared file. namespace { _Swallow_assign ignore; }; // anonymous namespace 

C’est pour que tu puisses faire

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

Les variables du côté gauche sont affectées aux éléments du some_tuple (voir ici ), une technique similaire est utilisée pour cet iterator. Le deuxième élément est ignoré.

Mais comme ils le disent, il devrait être placé dans un fichier .cpp et l’instance unique devrait être partagée par tous les utilisateurs. Ils mettraient une déclaration dans l’en-tête comme ceci:

 extern _Swallow_assign ignore; 

Je l’ai déjà 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 en cas de conflit 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 

Je ne vois vraiment aucun avantage à utiliser des espaces de noms anonymes dans les en-têtes. La confusion qui peut résulter du fait d’avoir la même déclaration de symbole signifie, en substance, une chose différente dans les unités de compilation qui incluent cet en-tête serait un moyen sûr de passer prématurément et douloureusement chauve.

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