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



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

  • std::make_uniquestd::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));

^如上所述,从tuple创建std::array也是非法的,因为 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_实用程序方法都已经使用了圆括号初始化。

因为在 C++98 中使用大括号初始化列表无法初始化结构。

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

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

相关内容

  • 没有找到相关文章

最新更新