2010-08-05 8 views
38

Me pregunto si la tupla se puede inicializar con la lista de inicializadores (para ser más precisos, con initializer_list of initializer_lists)? Teniendo en cuenta la definición tupla:Inicializando std :: tuple desde la lista de inicializadores

typedef std::tuple< std::array<short, 3>, 
        std::array<float, 2>, 
        std::array<unsigned char, 4>, 
        std::array<unsigned char, 4> > vertex; 

¿hay alguna manera de hacer lo siguiente:

static vertex const nullvertex = { {{0, 0, 0}}, 
            {{0.0, 0.0}}, 
            {{0, 0, 0, 0}}, 
            {{0, 0, 0, 0}} }; 

sólo quiero alcanzar misma funcionalidad que tengo uso de struct en lugar de tupla (por lo tanto sólo matrices se inicializan por initializer_list):

static struct vertex { 
    std::array<short, 3> m_vertex_coords; 
    std::array<float, 2> m_texture_coords; 
    std::array<unsigned char, 4> m_color_1; 
    std::array<unsigned char, 4> m_color_2; 
} const nullvertex = { 
    {{0, 0, 0}}, 
    {{0.0, 0.0}}, 
    {{0, 0, 0, 0}}, 
    {{0, 0, 0, 0}} 
}; 

No hay ninguna razón por la que deba usar tuplas, solo me pregunto. Pregunto, porque no puedo pasar por los errores de las plantillas g ++ generados por mi intento de inicialización de tuplas.

@Motti: Por lo que se perdió la sintaxis adecuada para la inicialización uniforme -

static vertex const nullvertex = vertex{ {{0, 0, 0}}, 
             {{0.0, 0.0}}, 
             {{0, 0, 0, 0}}, 
             {{0, 0, 0, 0}} }; 

y

static vertex const nullvertex{ {{0, 0, 0}}, 
           {{0.0, 0.0}}, 
           {{0, 0, 0, 0}}, 
           {{0, 0, 0, 0}} }; 

Pero parece que todo el problema reside en las matrices, las cuales recibieron ningún constructor para initializer_list y envolver matrices con el constructor adecuado parece una tarea no tan fácil.

Respuesta

40

Las listas de inicializadores no son relevantes para tuplas.

Creo que estás confundiendo dos usos diferentes de las llaves en C++ 0x.

  1. initializer_list<T> es una colección homogénea (todos los miembros deben ser del mismo tipo, por lo que no es relevante para std::tuple)
  2. Uniform initialization es donde se utilizan llaves con el fin de construir todo tipo de objetos; matrices, POD y clases con constructores. Que también tiene la ventaja de resolver the most vexing parse)

Aquí hay una versión simplificada:

std::tuple<int, char> t = { 1, '1' }; 
// error: converting to 'std::tuple<int, char>' from initializer list would use 
// explicit constructor 'std::tuple<_T1, _T2>::tuple(_U1&&, _U2&&) 
// [with _U1 = int, _U2 = char, _T1 = int, _T2 = char]' 

std::tuple<int, char> t { 1, '1' }; // note no assignment 
// OK, but not an initializer list, uniform initialization 

El mensaje de error dice es que usted está tratando de llamar de forma implícita al constructor pero es un constructor explícito para que pueda 't.

Básicamente lo que estamos tratando de hacer es algo como esto:

struct A { 
    explicit A(int) {} 
}; 

A a0 = 3; 
// Error: conversion from 'int' to non-scalar type 'A' requested 

A a1 = {3}; 
// Error: converting to 'const A' from initializer list would use 
// explicit constructor 'A::A(int)' 

A a2(3); // OK C++98 style 
A a3{3}; // OK C++0x Uniform initialization 
+0

Gracias por la respuesta! – erjot

+5

¿Por qué es malo construir una 'std :: tuple' con una lista init reforzada? Funciona para 'std :: pair's, y' std :: tuple' es la generalización de 'std :: pair', por lo que no entiendo el motivo de esta limitación: S ... – rubenvb

+4

@rubenvb está bien inicializar una 'tupla' con inicialización uniforme (llaves) pero para hacerlo debe colocar el signo igual. Si tiene un signo igual significa que construye un temporal con el constructor de un parámetro aceptando una lista de inicialización y luego usa el constructor de copia del valor temporal (aunque el compilador puede eludir parte de esto). – Motti

Cuestiones relacionadas