Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Initializing std::tuple from initializer list

Tags:

c++

c++11

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):

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.

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

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.

like image 794
erjot Avatar asked Aug 05 '10 08:08

erjot


People also ask

How do you initialize STD tuple?

Initializing a std::tuple We can initialize a std::tuple by passing elements as arguments in constructor i.e. std::tuple<int, double, std::string> result1 { 22, 19.28, "text" }; // Creating and Initializing a tuple std::tuple<int, double, std::string> result1 { 22, 19.28, "text" };

Does initializer list run before constructor?

As already answered, initialization lists get completely executed before entering the constructor block. So it is completely safe to use (initialized) members in the constructor body.

Does initializer list call constructor?

And if we use Initializer List there are only two function calls: copy constructor + destructor call.

How do initializer lists work C++?

An initializer list starts after the constructor name and its parameters. The list begins with a colon ( : ) and is followed by the list of variables that are to be initialized – all of​ the variables are separated by a comma with their values in curly brackets.


1 Answers

Initializer lists aren't relevant for tuples.

I think that you're confusing two different uses of curly braces in 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 initialization is 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)

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 
like image 84
Motti Avatar answered Sep 23 '22 10:09

Motti