tipo - name type c++
¿Por qué S:: x no se usa odr? (3)
Al declarar
const int
, el compilador puede descartarlo por completo a menos que
utilice
su dirección.
Tomar
la dirección no es suficiente.
Descartar no significa que el valor no se evalúa, lo es, pero significa que no hay una dirección de memoria que contenga el valor const, el compilador simplemente reemplaza la variable const por su valor, ya que era solo una macro.
Además, al tomar un puntero y recuperar el valor del puntero, no impresiona mucho al compilador, simplemente lo ignora y usa el valor.
El siguiente código lo muestra, este código puede compilarse y ejecutarse (lo pruebo por varios compiladores, todavía no estoy seguro si fue compilado con éxito por todos ...) a pesar de que
S::x
no fue declarado:
#include <iostream>
using namespace std;
struct S
{
static const int x=0;
};
//const int S::x; //discarded
int main()
{
const int *px = &S::x; //taking the address
cout<< *px <<endl; //print the value - OK
return 0;
}
Pero si trato de usar la dirección en sí (no el valor) como:
cout<< px <<endl; //print the address - Will be failed
el enlace no pudo: "referencia indefinida a
S::x
".
Por lo tanto, mi conclusión es: tomar una dirección sin usarla, no cuenta en absoluto .
Considere este ejemplo de cppreference :
struct S { static const int x = 1; };
void f() { &S::x; } // discarded-value expression does not odr-use S::x
Estoy de acuerdo en que
&S::x
es una
expresión de valor descartado
, ya que el estándar dice (9.2, párrafo 1 [stmt.expr] de
n4700
)
Las declaraciones de expresión tienen la forma
expression-statement: expression_opt ;
La expresión es una expresión de valor descartado (Cláusula 8) ...
Sin embargo, ¿es eso suficiente para que
S::x
no se
use odr
?
6.2, el párrafo 3 [basic.def.odr] establece
Una variable
x
cuyo nombre aparece como una expresión potencialmente evaluadaex
es odr-utilizada porex
menos que
- ...
- si
x
es un objeto,ex
es un elemento del conjunto de resultados potenciales de una expresióne
, donde
- la conversión lvalue-to-rvalue (7.1) se aplica a
e
, oe
es una expresión de valor descartado (Cláusula 8) .
El problema es que la expresión de valor descartado
&S::x
no tiene resultados potenciales (lo que significa que
S::x
no es un resultado potencial de
&S::x
), como se puede ver en 6.2, párrafo 2 [basic.def .odr]:
... El conjunto de resultados potenciales de una expresión
e
se define de la siguiente manera:
- Si
e
es una expresión id (8.1.4), el conjunto contiene soloe
.- Si
e
es una operación de suscripción (8.2.1) con un operando de matriz, el conjunto contiene los resultados potenciales de ese operando.- ...
- De lo contrario, el conjunto está vacío.
Entonces, ¿cómo puedes explicar que
S::x
no se usa odr?
De hecho, se usa odr. Su análisis es correcto (y arreglé ese ejemplo hace un tiempo ).
Sí, en el ejemplo,
&S::x
odr-usa
S::x
.
[basic.def.odr]/4
Una variable
x
cuyo nombre aparece como una expresión potencialmente evaluadaex
es odr-utilizada porex
menos que la aplicación de la conversión de lvalue-to-rvalue ax
produzca una expresión constante que no invoque ninguna función no trivial y, si x es un objeto , ex es un elemento del conjunto de resultados potenciales de una expresión e, donde la conversión de valor a valor r se aplica a e, oe es una expresión de valor descartado.
La dirección de un objeto nunca es una expresión constante.
Es por eso que
S::x
se usa odr en
&S::x
.
Para justificar esa última afirmación:
[expr.const]/6
Una expresión constante es una expresión constante central de glvalue que se refiere a una entidad que es un resultado permitido de una expresión constante (como se define a continuación), o una expresión constante central de prvalue cuyo valor satisface las siguientes restricciones [...]
y
[expr.const]/2.7
2) Una expresión
e
es una expresión constante central a menos que la evaluación dee
, siguiendo las reglas de la máquina abstracta , evalúe una de las siguientes expresiones:
[...]
2.7) una conversión lvalue-to-rvalue a menos que se aplique a
(ninguno de los siguientes puntos se aplica :)
2.7.1) un valor gl no volátil de tipo integral o de enumeración que se refiere a un objeto const no volátil completo con una inicialización anterior, inicializado con una expresión constante, o
2.7.2) un valor gl no volátil que se refiere a un subobjeto de un literal de cadena, o
2.7.3) un valor gl no volátil que se refiere a un objeto no volátil definido con constexpr, o que se refiere a un subobjeto no mutable de dicho objeto, o
2.7.4) un valor gl no volátil de tipo literal que se refiere a un objeto no volátil cuya vida útil comenzó dentro de la evaluación dee
;