2010-08-05 17 views
38

Zastanawiam się, czy krotka może być zainicjalizowana przez listę inicjalizującą (a dokładniej - przez initializer_list of initializer_lists)? Biorąc pod uwagę definicję krotka:Inicjalizacja std :: tuple z listy inicjalizatora

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

jest jakiś sposób, wykonując następujące czynności:

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

Chcę tylko, aby osiągnąć tę samą funkcjonalność dostałem użyciu struct zamiast krotki (a więc tylko tablice są inicjowane przez 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}} 
}; 

Nie ma powodu, dla którego muszę używać krotek, tylko się zastanawiam. Pytam, ponieważ nie jestem w stanie przejść przez błędy w szablonach g ++, które są generowane przez moją próbę zainicjowania takiej krotki.

@Motti: Więc brakowało właściwej składni jednolitej inicjalizacji -

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

i

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

Ale wydaje się, że cały problem polega na tablicach, które dostali żadnego konstruktora dla initializer_list i pakowanie tablic z odpowiednim konstruktorem nie wydaje się tak łatwym zadaniem.

Odpowiedz

40

Listy inicjalizacyjne nie dotyczą krotek.

Myślę, że mylicie dwa różne zastosowania nawiasów klamrowych w C++ 0x.

  1. initializer_list<T> jest jednorodny zbiór (wszyscy członkowie muszą być tego samego typu, to nie ma znaczenia dla std::tuple)
  2. Uniform initialization gdzie nawias klamrowy stosuje się w celu skonstruowania wszystkie rodzaje przedmiotów; tablice, POD i klasy z konstruktorami. Który ma również korzyści rozwiązywania the most vexing parse)

Oto uproszczona wersja:

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 

Komunikat o błędzie mówi, jest to, że starasz się niejawnie wywołanie konstruktora, ale jest to wyraźny konstruktor, dzięki czemu można "t.

Zasadniczo co starasz się zrobić coś takiego:

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

Dziękuję za odpowiedzi! – erjot

+5

Dlaczego konstruowanie 'std :: tuple' ze stężoną listą init jest złe? Działa dla 'std :: pair's, a' std :: tuple' jest uogólnieniem 'std :: pair', więc nie rozumiem powodu tego ograniczenia: S ... – rubenvb

+4

@rubenvb można zainicjować 'krotkę' z jednolitą inicjalizacją (nawiasy klamrowe), ale aby to zrobić, musisz upuścić znak równości. Jeśli masz znak równości, oznacza to, że tworzysz tymczasowy z jednym konstruktorem parametrów akceptującym listę inicjalizacyjną, a następnie używasz konstruktora kopiowania z wartości tymczasowej (chociaż kompilator może to znieść). – Motti

Powiązane problemy