为什么大小不是 std::initializer_list 的模板参数?
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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
如果
initializer_list
定义为std::initializer_list
,则任何采用initializer_list< 的函数/code>,其中
type
是某种具体类型,现在必须是基于该列表大小的模板函数。或者他们必须要求用户传递特定类型和大小的initializer_list
。和大小。这两点都是非常令人难以接受的。并非每个人都将所有代码编写为模板。
您可以从花括号初始化列表(中间有内容的
{}
)初始化std::array
。但这与 std::intiializer_list 不同。array
类是聚合类型。它是一个包含单个元素的结构,该元素是一个公共数组。因此,在符合 C++11 的实现上,应该可以编译:但是,
{1, 3, 5}
不是std::initializer_list
对象;它只是一个花括号初始化列表,可用于初始化适当的类型。您无法将
std::initializer_list
对象传递给聚合的构造函数(因为聚合没有构造函数),但您可以使用花括号初始化列表来调用聚合初始化来初始化std::array
,就像处理任何包含数组的结构一样。std::initializer_list
和花括号初始化列表之间的区别有点像int
和文字0
之间的区别。将int
对象隐式转换为指针类型(通常)是不合法的,但将整数文字 0 隐式转换为指针类型是合法的。 braced-init-lists 的工作方式是这样的:If
initializer_list
was defined asstd::initializer_list<type, size>
, then any function that takes aninitializer_list<type>
, wheretype
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 aninitializer_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 astd::intiializer_list
. Thearray
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:However,
{1, 3, 5}
is not astd::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 astd::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 anint
and the literal0
. It's not (usually) legal to implicitly convert anint
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:现有系统的一个优点是您可以导出从 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.