为什么 `make_<something>` 的标准首选圆括号初始化?

Why the standard preferred round brackets initialization for `make_<something>`?

标准中的std::make_函数,如:

内部全部使用圆括号初始化而不是花括号.

例如,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_tupleP0209r2,似乎没有讨论T(params...)T{params...}这两个备选方案,可能是因为所有类似的make_效用方法已经使用圆括号初始化。

因为在 C++98 中无法使用 braced-init-list 初始化结构。

因此,为了保持一致性,新的标准库功能使用了与 STL 中使用的相同的初始化形式。

此外,出于兼容性原因,它从未更改为列表初始化:列表初始化与等效的括号初始化形式不一定具有相同的含义。