Tengo algunas preguntas sobre el enlace de las siguientes variables. Por ejemplos de 7.1.1/7 de C++ 03 y experimentando con los compiladores (Comeau, Clang y GCC), llegué a los siguientes tipos de enlace:Vinculación de varias variables estáticas/estáticas
Primera
static
, entoncesextern
static int a; // (a) extern int a; // (b) valid, 'a' still internal
Es claro para mí de acuerdo con la sección 3.5: (a) implica vinculación interna. Y (b) también implica vinculación interna, porque el nombre "a" se declara estático (por (a)).
Primera
extern
, entoncesstatic
extern int b; // (c) static int b; // (d) invalid!
En primer lugar, (c) implica la vinculación externa. Pero (d) implica una vinculación interna porque el nombre "b" se declara estático por (d). Esto no es válido de acuerdo con 7.1.1/7, ya que la vinculación implícita no es consistente.
Primera
const
, entoncesextern
const double pi1 = 3.14; // (e) extern const double pi1; // (f) valid and 'pi1' is internal
En primer lugar, (e) implica enlace interno, porque es constante, y tampoco lo declarado extern explícita ni implícita vinculación externa con anterioridad. Y (f) debería implicar un enlace externo y ser un error, porque explícitamente declara el nombre extern, ¡pero los compiladores lo mantienen interno! ¿Por qué?Esa es mi pregunta.
Primera
extern
, entoncesconst
extern const double pi2; // (g) const double pi2 = 3.14; // (h) valid and 'pi2' is external
Ahora, (g) implica la vinculación externa porque declaramos explícitamente extern. Y (h) también implica un enlace externo porque (g) explícitamente declarado extern.
he encontrado experimentalmente a cabo la unión de 3 y 4 con la plantilla siguiente (se requiere que el segundo argumento de tener enlazado externo)
template<typename T, T&> struct ensure { };
ensure<const double, pi1> e1; // failed
ensure<const double, pi2> e2; // succeeded
Resumen: La Discusión con Charles Bailey resultó ser bastante fructífera y mostró que hay dos posibles interpretaciones de 3.5/3
, donde la importancia nt punto de viñeta dice
Un nombre que tiene un ámbito de espacio de nombres (3.3.5) tiene enlace interno si es el nombre de
- un objeto o de referencia que se declara explícitamente const y extern ni declarado explícitamente ni declarado previamente tener vinculación externa;
Si nos fijamos en el punto (f)
, a continuación, las dos interpretaciones llegan a conclusiones diferentes, como se muestra a continuación
La primera interpretación señala que se declara
pi1
const
sino que también se declaraextern
. La variable tiene así external vinculación.La segunda interpretación interpreta ambas ocurrencias de "declarado" para hacer referencia a la misma declaración. De esta forma, significa que está declarado
const
, pero noextern const
. Observamos que(e)
se declaraconst
y noextern const
, por lo que damospi1
enlace interno.
¿Qué interpretación es correcta? No puedo determinar a partir de esa redacción, pero los compiladores parecen interpretar esto de la segunda manera. En particular, si tomamos la primera interpretación, entonces la última parte citada de 3.5/3
sería superflua, porque no habría un escenario válido en el que un nombre se declararía const
y se declararía previamente con un enlace externo pero sin un extern
explícito.
Tal vez me falta algo, ¿pero 3 no es lo mismo que 1? (Es decir, ¿el nombre 'pi1' está 'declarado estático' por así decirlo?). Aunque supongo que solo le pregunté por qué 4 no es inválido. – GManNickG
@GMan, consulte 3.5/3 para estos dos casos. Se manejan por diferentes puntos de viñeta. –
@GMan para 4, el primero lo hizo externo y el segundo no lo convierte en interno, porque el nombre fue declarado explícitamente externo (por la primera declaración). Entonces, solo el primero, así como el primero y el segundo juntos implican el mismo vínculo. Para 2, solo el primero implica un enlace externo, pero el primero y el segundo juntos implican un enlace interno porque el nombre se declara explícitamente estático por el segundo. Por lo tanto, no es válido. –