Стандартные функции std::make_
, такие как:
std::make_unique
иstd::make_shared
std::make_tuple
std::make_from_tuple
все используют внутреннюю инициализацию с круглыми скобками, а не фигурные скобки.
Например, make_from_tuple
в соответствии со стандартом предпочитает возвращать T(params...)
, а не чем T{params...}
.
В результате следующие действия являются незаконными:
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));
^создание std::array
из tuple
, как указано выше, недопустимо также с C++20, как p0960 - позволяя инициализировать агрегаты из списка значений в скобках, становящегося частью спецификация C++20 не допускает такой инициализации для std::array
, так как его внутренний тип — T[size]
, который не может быть инициализирован из списка значений (круглые скобки уже удаляются инициализацией std::array
).
В тех случаях, когда это работает, выбор инициализации скобок вместо фигурных скобок имеет смысл:
auto vec2 = std::make_from_tuple<std::vector<int>>(std::make_tuple(2, 3));
// a vector with the values: {3, 3} surprise? :-)
(Конечно, выше приведены забавные примеры. Предоставленный кортеж может быть предоставлен извне).
С curly_make_from_tuple
вроде:
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));
}
все приведенные выше случаи будут работать, и можно утверждать, что это более естественно:
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}
Возникает вопрос: почему стандарт выбрал инициализацию с круглыми скобками вместо фигурных скобок?
Ссылки по теме:
Аналогичный вопрос с точки зрения эффективности: Почему реализация make_tuple не возвращается через инициализацию фигурной скобки?
Хорошее обсуждение и предложения по добавлению инициализации фигурных скобок опция для утилит `make_`.
Исходный документ с предложением make_from_tuple
, P0209r2, кажется, не обсуждают две альтернативы T(params...)
и T{params...}
, может быть, потому, что все аналогичные make_
служебные методы уже использовали инициализацию в круглых скобках.
T(std::forward<decltype(x)>(x) ... )
вместоT{std::forward<decltype(x)>(x) ... }
? - person NathanOliver   schedule 26.05.2020std::make_unique
,std::make_shared
,std::make_tuple
и т. д. не инициализируют вещи, они возвращают объекты, и их преимуществами являются потокобезопасность, простота и т. д. - person asmmo   schedule 26.05.2020