Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why do `initializer_list<pair>` and `initializer_list<tuple>` behave differently?

The following code compiles and runs :

#include <initializer_list>
#include <iostream>
#include <vector>
#include <tuple>

void ext( std::initializer_list<std::pair<double, std::vector<double> >> myList )
{
    //Do something
}

///////////////////////////////////////////////////////////

int main(void) {
    ext( { {1.0, {2.0, 3.0, 4.0} } } );
    return 0;
}

While this one does not :

#include <initializer_list>
#include <iostream>
#include <vector>
#include <tuple>

void ext( std::initializer_list<std::tuple<double, std::vector<double> >> myList )
{
    //Do something
}

///////////////////////////////////////////////////////////

int main(void) {
    ext( { {1.0, {2.0, 3.0, 4.0} } } );
    return 0;
}

The sole difference is that in the first case the ext() function takes an argument of type initializer_list<pair> (works) while the other uses initializer_list<tuple> (does not work). However, cplusplus.com states that

Pairs are a particular case of tuple.

So why does one code work and the other not ?


Additional information

The error outputted by clang++ in the second case is :

main.cpp:33:2: error: no matching function for call to 'ext'
      ext( { {1.0, {2.0, 3.0, 4.0} } } );
      ^~~
main.cpp:7:6: note: candidate function not viable: cannot convert initializer list argument to 'std::tuple<double,
      std::vector<double, std::allocator<double> > >'
void ext( std::initializer_list<std::tuple<double, std::vector<double> >> myList )
      ^
1 error generated.

while g++ outputs :

main.cpp: In function ‘int main()’:
main.cpp:33:35: error: converting to ‘std::tuple<double, std::vector<double, std::allocator<double> > >’ from initializer list would use explicit constructor ‘constexpr std::tuple<_T1, _T2>::tuple(const _T1&, const _T2&) [with _T1 = double; _T2 = std::vector<double>]’
  ext( { {1.0, {2.0, 3.0, 4.0} } } );
                                   ^
like image 558
Gael Lorieul Avatar asked Apr 07 '16 12:04

Gael Lorieul


1 Answers

cplusplus.com is not a very good site, because it is full of false statement like "Pairs are a particular case of tuple." You could use cppreference instead. In fact pair is not a particular case of tuple.

It's considered now that tuple is the better design; pair is quite a lot older and can't be changed now because of backwards compatibility.

The error message indicates that the difference is that tuple has an explicit constructor, but pair doesn't.

This means you need to mention the class name when constructing a tuple:

 ext( { std::tuple<double,std::vector<double>>{1.0, {2.0, 3.0, 4.0} } } );

This will be changed in C++17: the constructor of tuple will be explicit if and only if one of the tuple's types is class type with explicit constructor. gcc 6 already implements this feature. (Credit - Jonathan Wakely). See N4387

like image 56
M.M Avatar answered Oct 18 '22 23:10

M.M