Globales estáticos y espacios de nombres anónimos en C ++

11
  1. ¿Por qué C ++ hizo alguna distinción entre globales estáticos (enlace interno) y símbolos en un espacio de nombres sin nombre (enlace externo, pero no hay forma de referirse a él desde afuera de todos modos), al introducir este último?

  2. ¿Alguna de esas razones sigue siendo válida o hay otras nuevas?

  3. ¿Quedan lugares donde aún son diferentes, pero la regla arbitraria que deben ser las uniones anónimas globales (o del espacio de nombres)static , y cuáles son?

  4. Para los puntos de bonificación, si no quedan buenas razones para que sean diferentes, ¿hay alguna solicitud para que sean equivalentes?


Cuando C ++ introdujo espacios de nombres (C ++ 98), y espacios de nombres específicamente sin nombre, los globales estáticos fueron desaprobados como obsoletos e inferiores a lo nuevo en un ataque de entusiasmo, aunque eso se revirtió con C ++ 11 :
Desaprobación de la palabra clave estática ... ¿no más?

Antes de C ++ 11, los símbolos con enlace interno no podían usarse como argumentos de plantilla: ¿Por qué C ++ 03 requería que los parámetros de plantilla tuvieran enlace externo?

Deduplicador
fuente
Parece que ha respondido principalmente a su propia pregunta, excepto por el bit de "implementación conforme"; ¿Quizás debería considerar eliminar la segunda mitad y publicarla como respuesta? ¿O todavía hay algo sin respuesta aquí?
Kyle Strand
@KyleStrand lo reformuló todo.
Deduplicador

Respuestas:

3

No creo que esto responda a todas sus preguntas (¿o alguna de ellas?), Pero la diferencia clave entre las declaraciones estáticas a nivel de archivo y los espacios de nombres anónimos es que los espacios de nombres también se aplican a los tipos (no puede declarar un statictipo en el en el mismo sentido que declaras una variable), es por eso que se prefiere el espacio de nombres, por lo que hay un solo modismo para declarar datos y tipos con alcance de archivo.

A modo de ejemplo, el siguiente código debería compilarse perfectamente. (No es realmente útil, ya que no puede distinguir entre ambos tipos, pero está permitido)

#include <iostream>

struct Foobar
{
    int   foo;
    float bar;
};

namespace
{

struct Foobar
{
    double baz;
};

} // namespace

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

Una prueba en vivo aquí .

glampert
fuente
Se compila porque no usas Foobar en la función principal.
dshil
Más importante aún, ¿qué sucede si otro archivo .cpp declara su propia versión de struct Foobar? Peor aún, supongamos que es ahora class Foobar. Piensa en cómo planeas crear constructores para ambos.
dgnuff