为什么大小不是 std::initializer_list 的模板参数?

发布于 2024-11-30 00:53:07 字数 199 浏览 0 评论 0原文

std::initializer_list 由编译器根据大括号括起来的初始化列表构造,并且该列表的大小必须是编译时常量。

那么为什么委员会决定从模板参数中省略大小呢?这可能会阻止某些优化并使某些事情变得不可能(从 std::initializer_list 初始化 std::array)。

std::initializer_list is constructed by the compiler from a brace-enclosed init list and the size of this list must be a compile time constant.

So why did the committee decide to omit the size from the template arguments? This possibly prevents some optimizations and makes some things impossible (initializing std::array from a std::initializer_list).

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

慕烟庭风 2024-12-07 00:53:07

如果 initializer_list 定义为 std::initializer_list,则任何采用 initializer_list< 的函数/code>,其中 type 是某种具体类型,现在必须是基于该列表大小的模板函数。或者他们必须要求用户传递特定类型和大小的initializer_list和大小

这两点都是非常令人难以接受的。并非每个人都将所有代码编写为模板。

您可以从花括号初始化列表(中间有内容的 {})初始化 std::array。但这与 std::intiializer_list 不同。 array 类是聚合类型。它是一个包含单个元素的结构,该元素是一个公共数组。因此,在符合 C++11 的实现上,应该可以编译:

std::array<int, 3> myArray = {1, 3, 5};

但是,{1, 3, 5} 不是 std::initializer_list 对象;它只是一个花括号初始化列表,可用于初始化适当的类型。

您无法将 std::initializer_list 对象传递给聚合的构造函数(因为聚合没有构造函数),但您可以使用花括号初始化列表来调用聚合初始化来初始化 std::array,就像处理任何包含数组的结构一样。

std::initializer_list 和花括号初始化列表之间的区别有点像 int 和文字 0 之间的区别。将 int 对象隐式转换为指针类型(通常)是不合法的,但将整数文字 0 隐式转换为指针类型是合法的。 braced-init-lists 的工作方式是这样的:

int i = 0;    //Legal
void *j = 0;  //Legal
void *k = i;  //Not legal

std::array<int, 3> myArray = {1, 3, 5};             //Legal
std::initializer_list<int> myInitList = {1, 3, 5};  //Legal
std::array<int, 3> myArray = myInitList;            //Not legal

If initializer_list was defined as std::initializer_list<type, size>, then any function that takes an initializer_list<type>, where type is some concrete type, would now have to be a template function based on that list's size. Or they would have to require that users pass an initializer_list of a specific type and size.

Both of these are pretty unacceptable. Not everyone writes all of their code as templates.

You can initialize a std::array from a braced-init-list ({} with stuff in the middle). But that's not the same thing as a std::intiializer_list. The array class is an aggregate type. It is a struct that contains a single element, which is a public array. Therefore, on a conforming C++11 implementations, this should compile:

std::array<int, 3> myArray = {1, 3, 5};

However, {1, 3, 5} is not a std::initializer_list object; it is merely a braced-init-list, which can be used to initialize appropriate types.

You cannot pass a std::initializer_list object to the constructor of an aggegate (because aggregates have no constructors), but you can use a braced-init-list to invoke aggregate initialization to initialize a std::array, just as you would for any struct containing an array.

The difference between a std::initializer_list and a braced-init-list is a bit like the difference between an int and the literal 0. It's not (usually) legal to implicitly convert an int object into a pointer type, but it is legal to implicitly convert an integer literal 0 into a pointer type. The way braced-init-lists work is like that:

int i = 0;    //Legal
void *j = 0;  //Legal
void *k = i;  //Not legal

std::array<int, 3> myArray = {1, 3, 5};             //Legal
std::initializer_list<int> myInitList = {1, 3, 5};  //Legal
std::array<int, 3> myArray = myInitList;            //Not legal
独自唱情﹋歌 2024-12-07 00:53:07

现有系统的一个优点是您可以导出从 DLL 获取 initializer_list 的函数。如果它是按照尺寸模板化的,则它们必须作为来源发货。

One upside of the existing system is that you can export functions which take an initializer_list from a DLL. If it were templated on the size, they would have to be shipped as source.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文