The std::make_
functions in the standard, such as:
std::make_unique
andstd::make_shared
std::make_tuple
std::make_from_tuple
all use internally round brackets initialization rather than curly brackets.
For example, make_from_tuple
as presented by the standard is choosing to return T(params...)
rather than T{params...}
.
The result is that the following are illegal:
auto vec = std::make_from_tuple<std::vector<int>>(std::make_tuple());
auto arr = std::make_from_tuple<std::array<int, 2>>(std::make_tuple(9, 8));
^ the creation of std::array
from a tuple
, as above, is illegal also with C++20, as p0960 - allowing initialization of aggregates from a parenthesized list of values becoming part of the C++20 spec doesn't allow such initialization for std::array
, as its inner type is T[size]
which cannot be initialized from a list of values (the parentheses are already being stripped by std::array
initialization).
In cases where it does work, the selection of brackets initialization vs. curly brackets is meaningful:
auto vec2 = std::make_from_tuple<std::vector<int>>(std::make_tuple(2, 3));
// a vector with the values: {3, 3} surprise? :-)
(Above are of course toy examples. The supplied tuple may be provided externally).
With a curly_make_from_tuple
like:
template<typename T, typename tuple_t>
constexpr auto curly_make_from_tuple(tuple_t&& tuple) {
constexpr auto get_T = [](auto&& ... x){ return T{std::forward<decltype(x)>(x) ... }; };
return std::apply(get_T, std::forward<tuple_t>(tuple));
}
all cases above would work, in a way that one may argue is more natural:
auto arr = curly_make_from_tuple<std::array<int, 2>>(std::make_tuple(9, 8)); // {9, 8}
auto vec = curly_make_from_tuple<std::vector<int>>(std::make_tuple()); // {}
auto vec2 = curly_make_from_tuple<std::vector<int>>(std::make_tuple(2, 3)); // {2, 3}
The question is: why the standard chose round brackets initialization over curly brackets?
Related links:
Similar question, from efficiency point of view: Why does implementation of make_tuple not return via brace initialisation?
A nice discussion and suggestions for adding curly brackets initialization option for the `make_` utilities.
The original paper proposing make_from_tuple
, P0209r2, seem not to discuss the two alternatives T(params...)
and T{params...}
, maybe because all similar make_
utility methods had already been using round brackets initialization.