从初始化列表初始化std :: tuple

erj*_*jot 52 c++ c++11

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

typedef std::tuple< std::array<short, 3>,
                    std::array<float, 2>,
                    std::array<unsigned char, 4>,
                    std::array<unsigned char, 4> > vertex;
Run Code Online (Sandbox Code Playgroud)

有没有办法做到以下几点:

static vertex const nullvertex = { {{0, 0, 0}},
                                   {{0.0, 0.0}},
                                   {{0, 0, 0, 0}},
                                   {{0, 0, 0, 0}} };
Run Code Online (Sandbox Code Playgroud)

我只想实现使用struct而不是tuple的相同功能(因此只有数组由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}}
};
Run Code Online (Sandbox Code Playgroud)

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

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

static vertex const nullvertex = vertex{ {{0, 0, 0}},
                                         {{0.0, 0.0}},
                                         {{0, 0, 0, 0}},
                                         {{0, 0, 0, 0}} };
Run Code Online (Sandbox Code Playgroud)

static vertex const nullvertex{ {{0, 0, 0}},
                                {{0.0, 0.0}},
                                {{0, 0, 0, 0}},
                                {{0, 0, 0, 0}} };
Run Code Online (Sandbox Code Playgroud)

但似乎所有麻烦都在于数组,它没有初始化器列表的构造函数,并且使用适当的构造函数包装数组似乎不是那么容易的任务.

Mot*_*tti 55

初始化列表与元组无关.

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

  1. initializer_list<T>是一个同类集合(所有成员必须属于同一类型,因此不相关std::tuple)
  2. 统一初始化是使用花括号来构造各种对象的地方; 数组,POD和带有构造函数的类.哪个也有解决最烦恼的解析的好处)

这是一个简化版本:

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
Run Code Online (Sandbox Code Playgroud)

错误消息说是你试图隐式调用构造函数,但它是一个显式构造函数,所以你不能.

基本上你要做的是这样的事情:

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
Run Code Online (Sandbox Code Playgroud)

  • 为什么用括号初始化列表构造一个`std :: tuple`是一件坏事?它适用于`std :: pair`s,而`std :: tuple`是`std :: pair`的泛化,所以我不明白这个限制的原因:S ...... (10认同)
  • @rubenvb可以使用统一初始化(大括号)初始化`tuple`但是为了这样做,你必须删除等号.如果你有一个等号,那就意味着你用一个参数构造函数接受一个初始化列表来构造一个临时表,然后使用临时值中的复​​制构造函数(虽然编译器可以忽略其中的一些). (4认同)
  • 这是@rubenvb的一些非常糟糕的评论答案......不会引入临时性的.相应的构造函数是显式的只是一个很大的耻辱 (4认同)