Returning a tuple from a function using uniform initialization syntax
c++, c++11, gcc, tuples
Solution
Unlike for `pair<>`, implicit construction of a `tuple<>` is not possible unfortunately. You have to use `make_tuple()`:
#include <tuple>
std::tuple<double,double> dummy()
{
return std::make_tuple(2.0, 3.0); // OK
}
int main()
{
std::tuple<double,double> a = dummy();
return 0;
}
`std::tuple` has a variadic constructor, but it is marked as `explicit`. Thus, it cannot be used in this situation, where a temporary must be implicitly constructible. Per Paragraph 20.4.2 of the C++11 Standard:
namespace std {
template <class... Types>
class tuple {
public:
[...]
explicit tuple(const Types&...); // Marked as explicit!
template <class... UTypes>
explicit tuple(UTypes&&...); // Marked as explicit!
For the same reason it is illegal to use copy-initialization syntax for initializing tuples:
std::tuple<double, double> a = {1.0, 2.0}; // ERROR!
std::tuple<double, double> a{1.0, 2.0}; // OK
Or to construct a tuple implicitly when passing it as an argument to a function:
void f(std::tuple<double, double> t) { ... }
...
f({1.0, 2.0}); // ERROR!
f(make_tuple(1.0, 2.0)); // OK
Accordingly, if you construct your `std::tuple` explicitly when returning it in `dummy()`, no compilation error will occur:
#include <tuple>
std::tuple<double,double> dummy()
{
return std::tuple<double, double>{2.0, 3.0}; // OK
}
int main()
{
std::tuple<double,double> a = dummy();
return 0;
}
Problem
The following code compiles with clang (libc++) and fails with gcc (libstdc++). Why does gcc (libstdc++) complains about an initializer list? I thought the return argument was using uniform initialization syntax. ``` std::tuple<double,double> dummy() { return {2.0, 3.0}; } int main() { std::tuple<double,double> a = dummy(); return 0; } ``` Error: line 22: converting to ‘std::tuple’ from initializer \ list would use explicit constructor ‘constexpr std::tuple<_T1, _T2>::tuple(_U1&\ &, _U2&&) [with _U1 = double; _U2 = double; = void; _T\ 1 = double; _T2 = double]’ Note: GCC (libstdc++) (and clang (libc++)) accept ``` std::tuple<double,double> dummy {1.0, 2.0}; ``` Isn't it the same case? Update: this is a libc++ extension, see http://llvm.org/bugs/show_bug.cgi?id=15299 and also answer by Howard Hinnant below.