globaux statiques et espaces de noms anonymes en C ++

11
  1. Pourquoi C ++ a-t-il fait une distinction entre les globaux statiques (liaison interne) et les symboles dans un espace de noms sans nom (liaison externe, mais aucun moyen de s'y référer de l'extérieur de toute façon), lors de l'introduction de ce dernier?

  2. Certaines de ces raisons sont-elles toujours valables ou y en a-t-il de nouvelles?

  3. Y a-t-il des endroits où ils sont encore différents, mais la règle arbitraire que doivent être les unions anonymes globales (ou de portée d'espace de noms)static , et quelles sont-elles?

  4. Pour les points bonus, s'il n'y a plus de bonnes raisons pour qu'ils soient différents, y a-t-il une demande pour les rendre équivalents?


Lorsque C ++ a introduit les espaces de noms (C ++ 98), et spécifiquement les espaces de noms sans nom, les globaux statiques étaient obsolètes et inférieurs à la nouvelle chose dans un accès d'enthousiasme, bien que cela ait été inversé avec C ++ 11 :
Obsolescence du mot-clé statique… Pas plus?

Avant C ++ 11, les symboles avec liaison interne ne pouvaient pas être utilisés comme arguments de modèle: Pourquoi C ++ 03 nécessitait-il des paramètres de modèle pour avoir une liaison externe?

Déduplicateur
la source
Il semble que vous ayez principalement répondu à votre propre question, à l'exception du bit "mise en œuvre conforme"; vous devriez peut-être envisager de supprimer la seconde moitié et de la publier comme réponse à la place? Ou y a-t-il encore quelque chose sans réponse ici?
Kyle Strand
@KyleStrand Reformulé le tout.
Déduplicateur

Réponses:

3

Je ne suppose pas que cela réponde à toutes vos questions (ou à l'une d'entre elles?), Mais la principale différence entre les déclarations statiques au niveau des fichiers et les espaces de noms anonymes est que les espaces de noms s'appliquent également aux types (vous ne pouvez pas déclarer un statictype dans le même sens que vous déclarez une variable), c'est pourquoi l'espace de noms est préféré, donc il y a un idiome unique pour déclarer les types et les données de portée de fichier.

À titre d'exemple, le code suivant devrait compiler très bien. (Pas vraiment utile, car vous ne pouvez pas distinguer les deux types, mais autorisé)

#include <iostream>

struct Foobar
{
    int   foo;
    float bar;
};

namespace
{

struct Foobar
{
    double baz;
};

} // namespace

int main()
{
    std::cout << "HELLO!\n";
}

Un test en direct ici .

glampert
la source
Il compile parce que vous n'utilisez pas Foobar dans la fonction principale.
dshil
Plus important encore, que se passe-t-il si un autre fichier .cpp déclare sa propre version de struct Foobar? Pire encore, supposons que ce soit maintenant class Foobar. Réfléchissez à la façon dont vous prévoyez de créer des constructeurs pour les deux.
dgnuff