31

To me a pair is just special case of a tuple, but following surprises me:

pair<int, int> p1(1, 2);   // ok
tuple<int, int> t1(1, 2);  // ok

pair<int, int> p2={1, 2};  // ok
tuple<int, int> t2={1, 2}; // compile error

Why there is difference when we use {} to initialize tuple?

I tried even g++ -std=c++1y but still has error:

a.cc: In function 'int main()':
a.cc:9:29: error: converting to 'std::tuple<int, int>' from initializer list would use explicit constructor 'constexpr std::tuple<_T1, _T2>::tuple(_U1&&, _U2&&) [with _U1 = int; _U2 = int; <template-parameter-2-3> = void; _T1 = int; _T2 = int]'
     tuple<int, int> t2={1, 2};
                             ^
Deqing
  • 14,098
  • 15
  • 84
  • 131

2 Answers2

30

In addition to Praetorian's correct answer (which I've upvoted), I wanted to add a little more information...

Post-C++14, the standard has been changed to allow:

tuple<int, int> t2={1, 2}; 

to compile and have the expected semantics. The proposal that does this is N4387. This will also allow constructs such as:

tuple<int, int>
foo()
{
    return {1, 2};
}

It only allows it if all T in the tuple are implicitly contructible from all arguments.

As a non-conforming extension, libc++ already implements this behavior.

Howard Hinnant
  • 206,506
  • 52
  • 449
  • 577
  • 1
    You say "non-conforming": does this extension change the behaviour of any code which is correct under C++14? – M.M Aug 19 '15 at 01:04
  • 10
    @MattMcNabb: Yes. `is_convertible>{}` is false in C++14 and true in C++1z. The powers of C++ introspection have gotten so strong that it is nearly impossible to write conforming extensions these days. – Howard Hinnant Aug 19 '15 at 01:57
  • If anyone has the rep for a 1-character edit, there's now an https version of that N4387 link. – AJM Nov 25 '22 at 15:57
27

The tuple constructor you're trying to call is explicit, so copy-list-initialization will fail. The corresponding pair constructor is not explicit.

Change your code to

tuple<int, int> t2{1, 2};

and it'll compile.

Community
  • 1
  • 1
Praetorian
  • 106,671
  • 19
  • 240
  • 328
  • 3
    Is there any reason that `tuple` uses explicit constructor? – Deqing Aug 19 '15 at 00:46
  • 2
    @Deqing If it didn't, then a `tuple` containing a single type could be implicitly constructed from a value that is convertible to that type. – Praetorian Aug 19 '15 at 00:48
  • 2
    @Praetorian To avoid that, perhaps tuple could have had explicit constructor taking one argument, and non-explicit constructor taking two or more? – M.M Aug 19 '15 at 00:51
  • @MattMcNabb See Howard's answer, looks like this has been fixed in a different manner – Praetorian Aug 19 '15 at 00:56