sirve que para lenguaje historia ejemplos descargar comandos caracteristicas c++ c++14 one-definition-rule

que - ¿Cuándo se usa una variable odr en C++ 14?



lenguaje c++ ejemplos (1)

El borrador de C ++ 14 (N3936) establece en §3.2 / 3:

Una variable x cuyo nombre aparece como una expresión potencialmente evaluada ex es odr-used, a menos que la aplicación de la conversión de valor a rvalor (4.1) a x produzca una expresión constante (5.19) 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 de r (4) se aplica a e, o e es una expresión de valor descartado (Cláusula 5).

Esto no tiene ningún sentido para mí: si una expresión e es una expresión de valor descartado depende del contexto en el que se utiliza e . Cada expresión utilizada en una expresión-declaración (§6.2) es una expresión de valor descartado . Si la conversión de lvalue a rvalue se aplica a e también depende del contexto en el que se usa e .

Además, ¿qué significa para una expresión estar en el conjunto de resultados potenciales de otra expresión? Se necesita una noción de igualdad de expresiones para poder determinar la pertenencia a un conjunto. Pero no tenemos transparencia referencial , por lo que no puedo ver cómo se puede lograr esto.

¿Por qué se cambió esto de C ++ 11 a C ++ 14? ¿Y cómo debe interpretarse esto? En su forma actual, no tiene sentido.


El propósito de odr-use

Informalmente, odr-uso de una variable significa lo siguiente:

Si alguna expresión en cualquier lugar del programa toma la dirección de o vincula una referencia directamente a un objeto, este objeto debe definirse.

Aclaración en el último borrador.

En la última versión de la especificación §3.2 se ha aclarado (ver Borrador C ++ 14 en GitHub ):

2 Una expresión se evalúa potencialmente a menos que sea un operando no evaluado (Cláusula 5) o una subexpresión del mismo. El conjunto de resultados potenciales de una expresión e se define de la siguiente manera:

  • Si e es una expresión-id (5.1.1), el conjunto solo contiene e .
  • Si e es una expresión de acceso de miembro de clase (5.2.5), el conjunto contiene los resultados potenciales de la expresión de objeto.
  • Si e es una expresión de puntero a miembro (5.5) cuyo segundo operando es una expresión constante, el conjunto contiene los resultados potenciales de la expresión del objeto.
  • Si e tiene la forma (e1), el conjunto contiene los resultados potenciales de e1.
  • Si e es una expresión condicional glvalue (5.16), el conjunto es la unión de los conjuntos de resultados potenciales del segundo y tercer operandos.
  • Si e es una expresión de coma (5.18), el conjunto contiene los resultados potenciales del operando correcto.
  • De lo contrario, el conjunto está vacío.

[Nota: este conjunto es un conjunto (posiblemente vacío) de expresiones-id, cada una de las cuales es e o una subexpresión de e .

[Ejemplo: en el siguiente ejemplo, el conjunto de resultados potenciales del inicializador de n contiene la primera subexpresión S::x , pero no la segunda subexpresión S::x .

struct S { static const int x = 0; }; const int &f(const int &r); int n = b ? (1, S::x) // S::x is not odr-used here : f(S::x); // S::x is odr-used here, so // a definition is required

—En el ejemplo] —en la nota final]

3 Una variable x cuyo nombre aparece como una expresión potencialmente evaluada ex es odr-used by ex menos que la aplicación de la conversión de valor a rvalor (4.1) a x produzca una expresión constante (5.19) 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 cualquiera de las conversiones de lvalue a valor (4.1) se aplica a e , o e es una expresión de valor descartado (Cláusula 5) .

¿Cuál era la situación en C ++ 11?

§3.2 / 2 en C ++ 11 lee:

Una expresión se evalúa potencialmente a menos que sea un operando sin evaluar (Cláusula 5) o una subexpresión del mismo. Una variable cuyo nombre aparece como una expresión potencialmente evaluada es odr-used a menos que sea un objeto que cumpla con los requisitos para aparecer en una expresión constante (5.19) y se aplique inmediatamente la conversión de lvalue a rvalue (4.1).

El problema con estas expresiones fue DR 712 . Considera este ejemplo:

struct S { static const int a = 1; static const int b = 2; }; int f(bool x) { return x ? S::a : S::b; }

Dado que S::a S::b son lvalues, la expresión condicional x ? S::a : S::b x ? S::a : S::b también es un lvalue. Esto significa que la conversión de lvalue a rvalue no se aplica inmediatamente a S::a y S::b , sino al resultado de la expresión condicional. Esto significa que, mediante la redacción de C ++ 11, estos miembros de datos estáticos se usan de forma estándar y se requiere una definición. Pero en realidad solo se usan los valores, por lo tanto, no es necesario definir los miembros de datos estáticos, una declaración sería suficiente. La nueva redacción del borrador C ++ 14 resuelve esto.

¿La nueva redacción resuelve todos los problemas?

No. En el siguiente ejemplo, la variable S::a todavía se usa de forma estándar:

struct S { static constexpr int a[2] = {0, 1}; }; void f() { auto x = S::a[0]; }

Por lo tanto, envié un nuevo issue para agregar la siguiente viñeta a §3.2 / 2:

  • si e es una expresión de subíndice de glvalor (5.2.1) de la forma E1[E2] , el conjunto contiene los resultados potenciales de E1 .