[英]Why are std::begin() and std::end() overloaded for std::initializer_list in C++11?
在C ++ 11(引用N3337)中, std::begin()
和std::end()
被指定为(§24.7[iterator.range] / p2-3)
template <class C> auto begin(C& c) -> decltype(c.begin()); template <class C> auto begin(const C& c) -> decltype(c.begin());
2返回:
c.begin()
。template <class C> auto end(C& c) -> decltype(c.end()); template <class C> auto end(const C& c) -> decltype(c.end());
3返回:
c.end()
。
但是, std::initializer_list
为这些函数提供了自己的重载(第18.9.3节[support.initlist.range]):
template<class E> const E* begin(initializer_list<E> il) noexcept;
1返回:
il.begin()
。template<class E> const E* end(initializer_list<E> il) noexcept;
2返回:
il.end()
。
似乎这些重载除了基本模板之外没有做任何事情,除了(1)具有noexcept
规范和(2)按值获取它们的参数。 但是,复制initializer_list
没有什么特别之处(它只是复制一对指针或同样轻量级的东西),因此(2)没有产生任何行为上的差异。 此外,许多标准容器的begin()
和end()
成员函数也是noexcept
,但没有为这些容器指定std::begin()
/ std::end()
重载,因此委员会似乎不太可能指定这些重载仅适用于(1)。 那么,为什么要提供这些重载?
这在N2930中进行了解释, N2930提出了更改以添加有问题的重载。 我的重点:
建议修改摘要
- 在不使用概念的情况下指定基于范围的语句,使用begin和end的参数依赖查找(它总是包括命名空间
std
begin
和end
函数),以提供序列开头和结尾的迭代器。- 指定基于范围的语句, 以便数组和初始化程序列表不依赖于
<iterator>
。- 重构
<initializer_list>
,使其不依赖于其他标头,并且不包含其他标头。- 指定要
#include <initializer_list>
的库头。
似乎他们没有解释为什么他们希望<initializer_list>
不依赖于<iterator>
,但我认为合理的猜测是前者应该在独立实现中可用,而后者可能不是(表16,§17.6.1.3)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.