type tipo not nombra name error does c++ language-lawyer c++17

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 evaluada ex es odr-utilizada por ex menos que

  • ...
  • si x es un objeto, ex es un elemento del conjunto de resultados potenciales de una expresión e , donde
    • la conversión lvalue-to-rvalue (7.1) se aplica a e , o
    • e 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 solo e .
  • 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 evaluada ex es odr-utilizada por ex menos que la aplicación de la conversión de lvalue-to-rvalue a x 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 de e , 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 de e ;