type over loop instead for based c++ c++11 language-lawyer stdtuple

loop - iterate over vector c++ 11



¿Se puede fallar una implementación de std:: tuple al desencadenar una conversión derivada a base para elementos de clase vacíos? (2)

Bajo la cláusula 17 Introducción a la biblioteca :

17.5.2.3 Miembros privados [objects.within.classes]

1 - Las cláusulas 18 a 30 y el Anexo D no especifican la representación de las clases, y omiten intencionalmente la especificación de los miembros de la clase. Una implementación puede definir miembros de clase estáticos o no estáticos, o ambos, según sea necesario para implementar la semántica de las funciones miembro especificadas en las Cláusulas 18 a 30 y el Anexo D.

Esto es compatible con 1.4 Cumplimiento de la implementación [intro.compliance] :

3 - Para las clases y las plantillas de clase, las cláusulas de la biblioteca especifican definiciones parciales. Los miembros privados (Cláusula 11) no se especifican, pero cada implementación los proporcionará para completar las definiciones de acuerdo con la descripción en las Cláusulas de la biblioteca.

La implementación de la semántica especificada a través de la herencia no se discute explícitamente en ninguna parte de la cláusula 17, pero está implícitamente permitida en el párrafo 3 de 17.5.2.3 anterior:

3 - Una implementación puede usar cualquier técnica que proporcione un comportamiento externo equivalente.

Así es como, por ejemplo, los contenedores asociativos ordenados basados ​​en nodos pueden compartir detalles de implementación (incluidos, eventualmente, miembros de clase) a través de la herencia.

Dado que el comportamiento externo de la tuple cambia entre tener A como miembro de una clase y su herencia directa, y dado que este cambio de comportamiento provoca el rechazo de programas bien formados (en lugar de simplemente cambiar el sizeof de una clase), libstdc ++ es en violación de la Norma.

Este código no se compila con GCC4.7

struct A {}; void f(A); struct B { B(std::tuple<A>); }; void f(B); int main() { f(std::make_tuple(A())); }

Porque GCC deriva de A para hacer uso de la optimización de clase base vacía. Sin embargo, eso hace que GCC elija f(A) y se queje

error: ''A'' es una base inaccesible de ''tuple<A>''

¿Este error es otorgado por el estándar de C ++ o es simplemente un error de libstdc ++?


Yo diría que no .

Por lo menos:

§20.4.1 [tuple.general]

1 / [...] Una instanciación de tupla con dos argumentos es similar a una instanciación de par con los mismos dos argumentos. Ver 20.3.

Y todavía:

#include <tuple> struct A {}; void f(A); struct B { B(std::tuple<A, A>); }; void f(B); int main() { f(std::make_tuple(A(), A())); }

fails con:

Compilation finished with errors: source.cpp: In function ''int main()'': source.cpp:10:30: error: ''A'' is an ambiguous base of ''std::tuple<A, A>'' source.cpp:4:6: error: initializing argument 1 of ''void f(A)''

Y dudo mucho que esta fuera la intención del Estándar.

Aún así, lo menos que se puede decir es que §20.4 es bastante breve ...