为什么 `make_<something>` 的标准首选圆括号初始化?
Why the standard preferred round brackets initialization for `make_<something>`?
标准中的std::make_
函数,如:
std::make_unique
和 std::make_shared
std::make_tuple
std::make_from_tuple
内部全部使用圆括号初始化而不是花括号.
例如,make_from_tuple
as presented by the standard 选择 return 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));
^ 从 tuple
创建 std::array
,如上所述,, as p0960 - allowing initialization of aggregates from a parenthesized list of values becoming part of the C++20 spec 不允许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}
问题是:为什么标准选择圆括号初始化而不是大括号?
相关链接:
类似问题,从效率的角度:
不错discussion and suggestions for adding curly brackets initialization option for the `make_` utilities.
原论文提出make_from_tuple
、P0209r2,似乎没有讨论T(params...)
和T{params...}
这两个备选方案,可能是因为所有类似的make_
效用方法已经使用圆括号初始化。
因为在 C++98 中无法使用 braced-init-list 初始化结构。
因此,为了保持一致性,新的标准库功能使用了与 STL 中使用的相同的初始化形式。
此外,出于兼容性原因,它从未更改为列表初始化:列表初始化与等效的括号初始化形式不一定具有相同的含义。
标准中的std::make_
函数,如:
std::make_unique
和std::make_shared
std::make_tuple
std::make_from_tuple
内部全部使用圆括号初始化而不是花括号.
例如,make_from_tuple
as presented by the standard 选择 return 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));
^ 从 tuple
创建 std::array
,如上所述,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}
问题是:为什么标准选择圆括号初始化而不是大括号?
相关链接:
类似问题,从效率的角度:
不错discussion and suggestions for adding curly brackets initialization option for the `make_` utilities.
原论文提出make_from_tuple
、P0209r2,似乎没有讨论T(params...)
和T{params...}
这两个备选方案,可能是因为所有类似的make_
效用方法已经使用圆括号初始化。
因为在 C++98 中无法使用 braced-init-list 初始化结构。
因此,为了保持一致性,新的标准库功能使用了与 STL 中使用的相同的初始化形式。
此外,出于兼容性原因,它从未更改为列表初始化:列表初始化与等效的括号初始化形式不一定具有相同的含义。