initialize enclosed brace argument c++ c++11 operators initializer-list

enclosed - c++ initializer list



Listas de inicializadores y RHS de operadores (1)

No entiendo por qué las listas de inicializadores no se pueden usar en el RHS de un operador. Considerar:

class foo { }; struct bar { template<typename... T> bar(T const&...) { } }; foo& operator<<(foo& f, bar const&) { return f; } int main() { foo baz; baz << {1, -2, "foo", 4, 5}; return 0; }

El último Clang (gcc también) se queja:

clang.cc:14:9: error: initializer list cannot be used on the right hand side of operator ''<<'' baz << {1, -2, "foo", 4, 5}; ^ ~~~~~~~~~~~~~~~~~~~~ ^ ~~~~~~~~~~~~~~~

¿Por qué el estándar C ++ lo prohibiría? O dicho de otra manera, ¿por qué falla esto en oposición a

baz << bar{1, -2, "foo", 4, 5};

?


De hecho, la versión final de C ++ 11 no permite el uso de listas de inicializadores en el lado derecho (o en el lado izquierdo, para el caso) de un operador binario.

En primer lugar, las listas de inicializadores no son expresiones tal como se definen en el §5 de la Norma. Los argumentos de las funciones, así como de los operadores binarios, generalmente tienen que ser expresiones, y la gramática para las expresiones definidas en el § 5 no incluye la sintaxis para las listas de inicialización-refuerzo (es decir, listas de inicializadores puras; con una lista de inicio de llaves, como bar {2,5,"hello",7} es una expresión, sin embargo).

Para poder utilizar convenientemente listas de inicializadores puras, la norma define varias excepciones, que se resumen en la siguiente nota (no normativa):

§8.5.4 / 1 [...] Nota: la inicialización de la lista puede ser utilizada
- como el inicializador en una definición variable (8.5)
- como inicializador en una nueva expresión (5.3.4)
- en una declaración de devolución (6.6.3)
- como argumento de función (5.2.2)
- como un subíndice (5.2.1)
- como argumento para una invocación de constructor (8.5, 5.2.3)
- como inicializador para un miembro de datos no estático (9.2)
- en un mem-initializer (12.6.2)
- en el lado derecho de una tarea (5.17)
[...]

El cuarto elemento anterior permite explícitamente listas de inicializadores puras como argumentos de funciones (por lo que el operator<<(baz, {1, -2, "foo", 4, 5}); funciona), el quinto lo permite en expresiones de subíndice (es decir, como argumento del operator[] , por ejemplo, mymap[{2,5,"hello"}] es legal), y el último elemento los permite en el lado derecho de las asignaciones (pero no en operadores binarios generales).

No existe tal excepción para los operadores binarios como + , * o << , por lo tanto, no puede poner una lista de inicializadores pura (es decir, una que no esté precedida por un nombre de tipo) a cada lado de ellos.

En cuanto a las razones para esto , un borrador / documento de debate N2215 de Stroustrup y Dos Reis de 2007 proporciona una gran cantidad de información sobre muchos de los problemas con las listas de inicializadores en varios contextos. Específicamente, hay una sección sobre operadores binarios (sección 6.2):

Considere usos más generales de las listas de inicializadores. Por ejemplo:

v = v+{3,4}; v = {6,7}+v;

Cuando consideramos a los operadores como azúcar sintáctico para funciones, naturalmente consideramos el equivalente anterior a

v = operator+(v,{3,4}); v = operator+({6,7},v);

Por lo tanto, es natural ampliar el uso de listas de inicializadores a expresiones. Hay muchos usos en los que las listas de inicializadores combinadas con operadores son una notación "natural".
Sin embargo, no es trivial escribir una gramática LR (1) que permita el uso arbitrario de las listas de inicializadores. Un bloque también comienza con un {permitiendo así una lista de inicializadores ya que la primera entidad (a la izquierda) de una expresión llevaría al caos en la gramática.
Es trivial permitir listas de inicializadores como el operando de la derecha de operadores binarios, en subíndices y partes aisladas similares de la gramática. El verdadero problema es permitir ;a={1,2}+b; como una declaración de asignación sin permitir también ;{1,2}+b; . Sospechamos que permitir las listas de inicializadores como mano derecha, pero ni [sic] como argumentos izquierdos para la mayoría de los operadores es demasiado [...]

En otras palabras, las listas de inicializadores no están habilitadas en el lado derecho porque no están habilitadas en el lado izquierdo , y no están habilitadas en el lado izquierdo porque eso hubiera representado un desafío demasiado grande para los analizadores .

Me pregunto si el problema podría haberse simplificado eligiendo un símbolo diferente en lugar de llaves para la sintaxis de la lista de inicializadores.