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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3413050/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-28 12:46:55  来源:igfitidea点击:

Initializing std::tuple from initializer list

c++c++11

提问by erjot

I'm wondering whether the tuple can be initialized by initializer list (to be more precise - by initializer_list of initializer_lists)? Considering the tuple definition:

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

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

is there any way of doing the following:

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

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

I just want to achieve same functionality I got using struct instead of tuple (thus only arrays are initialized by initializer_list):

我只想实现我使用 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}}
};

There is no reason I must use tuples, just wondering. I'm asking, because I'm unable to go through g++ templates errors which are generated by my attempt of such tuple initialization.

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

@Motti: So I missed the proper syntax for uniform initialization -

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

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

and

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

But it seems that all the trouble lies in arrays, which got no constructor for initializer_list and wrapping arrays with proper constructor seems not so easy task.

但似乎所有的麻烦都出在数组上,它没有用于 initializer_list 的构造函数,用适当的构造函数包装数组似乎不是那么容易的任务。

回答by Motti

Initializer lists aren't relevant for tuples.

初始化列表与元组无关。

I think that you're confusing two different uses of curly braces in C++0x.

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

  1. initializer_list<T>is a homogeneous collection (all members must be of the same type, so not relevant for std::tuple)
  2. Uniform initializationis where curly brackets are used in order to construct all kinds of objects; arrays, PODs and classes with constructors. Which also has the benefit of solving the most vexing parse)
  1. initializer_list<T>是同构集合(所有成员必须属于同一类型,因此与 无关std::tuple
  2. 统一初始化是使用大括号来构造各种对象;数组、POD 和带有构造函数的类。这也有解决最令人头疼的解析的好处)

Here's a simplified version:

这是一个简化版本:

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

The error message says is that you're trying to implicitly call the constructor but it's an explicit constructor so you can't.

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

Basically what you're trying to do is something like this:

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

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