Listas de inicializadores y RHS de operadores


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

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++ prohibiría esto? O dicho de otra manera, ¿por qué falla esto en lugar de

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

?

Author: mavam, 2012-07-10

1 answers

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

En primer lugar, las listas inicializadoras no son expresiones como se define en §5 del Estándar. 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 §5 no incluye la sintaxis para brace-init-lists( es decir, pure initializer-lists; nota que un nombre de tipo seguido de una lista de inicio de llaves, como bar {2,5,"hello",7} es una expresión, sin embargo).

Para poder usar listas inicializadoras puras convenientemente, el estándar define varias excepciones, que se resumen en la siguiente nota (no normativa):

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

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

There is no such exception for binary operators like +, * o <<, por lo tanto no puede poner una lista inicializadora pura (es decir, una que no esté precedida por un nombre de tipo) a cada lado de ellos.

En cuanto a las razones de este , un proyecto / 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 inicializadoras en varios contextos. Específicamente, hay una sección sobre operadores binarios (sección 6.2):

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

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

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

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

Por lo tanto, es natural ampliar el uso de inicializador lista las expresiones. Hay muchos usos donde las listas de inicializadores combinadas con operadores es una notación "natural".
Sin embargo, no es trivial escribir una gramática LR(1) que permita el uso arbitrario de listas inicializadoras. Un bloque también comienza con un { por lo que permitir una lista inicializadora como la primera entidad (más a la izquierda) de una expresión llevaría al caos en la gramática.
Es trivial permitir listas inicializadoras como el operando derecho 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 instrucción de asignación sin permitir también ;{1,2}+b;. Sospechamos que permitir listas inicializadoras como de la mano derecha, pero ni [sic] como argumentos de la mano izquierda para la mayoría de los operadores es demasiado de un kludge, [...]

En otras palabras, el inicializador de listas no están habilitadas en el lado derecho porque no están habilitados en el lado izquierdo, y no están habilitados en el lado izquierdo debido a que habría planteado 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 inicializadora.

 47
Author: jogojapan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-02-13 23:56:57