T.C*_*.C. 8 c++ initializer-list c++11
在C++ 11中(引用N3337),std::begin()并std::end()指定为(§24.7[iterator.range]/p2-3)
Run Code Online (Sandbox Code Playgroud)template <class C> auto begin(C& c) -> decltype(c.begin()); template <class C> auto begin(const C& c) -> decltype(c.begin());2返回:
c.begin().Run Code Online (Sandbox Code Playgroud)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]):
Run Code Online (Sandbox Code Playgroud)template<class E> const E* begin(initializer_list<E> il) noexcept;1返回:
il.begin().Run Code Online (Sandbox Code Playgroud)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的参数相关查找(总是包括命名空间中的那些
begin和end函数std)来为序列的开头和结尾提供迭代器.- 指定基于范围的语句,以便数组和初始化列表不依赖于
<iterator>.- 重构
<initializer_list>,使其不依赖于其他标头,并且不包含其他标头.- 指定要的库头
#include <initializer_list>.
似乎他们没有解释为什么他们不想<initializer_list>依赖<iterator>,但我认为合理的猜测是,前者应该是独立实施的,而后者可能不是(表16,§17.6.1.3) )