2010-08-05 197 views
38

我想知道元组是否可以通过初始化列表进行初始化(更确切地说 - initializer_list的initializer_list)?考虑到元组的定义:初始化从初始化列表中的std ::元组

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

有以下这样做的任何方式:

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

我只是想实现我使用结构,而不是元组相同的功能(因此只阵列由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}} 
}; 

没有理由我必须使用元组,只是想知道。我问,因为我无法通过由我尝试这种元组初始化生成的g ++模板错误。

@Motti:所以我错过了统一初始化的正确语法 -

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

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

但似乎所有的麻烦在于阵列,其中有没有构造函数initializer_list和用合适的构造函数包装数组似乎不是那么容易的任务。

回答

40

初始化列表与元组无关。

我认为你在C++ 0x中混淆了花括号的两种不同用法。

  1. initializer_list<T>是均匀的集合(所有成员必须是同一类型的,所以不适合std::tuple相关)
  2. Uniform initialization是其中大括号,以便构建各种对象的使用;数组,POD和具有构造函数的类。其中也有解决the most vexing parse的利益)

下面是一个简化版本:

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 

错误消息说的是,你试图隐含调用构造函数,但它是一个明确的构造函数,因此你可以“T。

基本上你想要做的是这样的:

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

感谢您的答复! – erjot 2010-08-06 09:06:58

+5

为什么用一个加载的init列表构造一个'std :: tuple'是一件坏事?它适用于'std :: pair's,'std :: tuple'是'std :: pair'的泛化,所以我不明白这个限制的原因:S ... – rubenvb 2012-08-28 19:36:02

+4

@rubenvb可以用统一的初始化(大括号)初始化一个'元组',但要做到这一点,你必须删除等号。如果你有一个等号,这意味着你使用一个参数构造函数构造一个临时接受一个初始化列表,然后从临时值中使用复制构造函数(尽管编译器可以省略其中的一部分)。 – Motti 2012-08-29 07:50:22