I don't understand why in foobar
below I need to specify std::vector<int>{}
whereas in foobar2
I do not:
#include <iostream>
#include <memory>
#include <vector>
#include <tuple>
std::tuple<std::unique_ptr<int>, std::vector<int>> foobar() {
std::unique_ptr<int> test = std::make_unique<int>(42);
return { std::move(test), {} }; // <= this is a syntax error
// return { std::move(test), std::vector<int>{} } // <= this compiles...
}
std::tuple<int, std::vector<int>> foobar2() {
return { {}, {} };
}
int main() {
std::cout << *std::get<0>(foobar()) << "\n";
std::cout << std::get<0>(foobar2()) << "\n";
return 0;
}
The error message from GCC is
<source>: In function 'std::tuple<std::unique_ptr<int, std::default_delete<int> >, std::vector<int, std::allocator<int> > > foobar()':
<source>:8:34: error: could not convert '{std::move<unique_ptr<int>&>(test), <brace-enclosed initializer list>()}' from '<brace-enclosed initializer list>' to 'std::tuple<std::unique_ptr<int, std::default_delete<int> >, std::vector<int, std::allocator<int> > >'
8 | return { std::move(test), {} }; // <= this is a syntax error
| ^
| |
| <brace-enclosed initializer list>
Compiler returned: 1
pair
constructors in C++23, which solves problems like this. Unfortunately, you can't default a pack in current C++23, so this solution isn't applicable to tuples. (But I hear there is a proposal.) – Theoretician