为什么在C++11中对std::initializer_list进行了std::begin()和std::end()的重载?

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()

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;

返回il.end()


它也被valarray重载了。 - 101010
对我来说,显而易见的区别是缺乏返回类型推断。这可能是在以后的修订中引入的吗?不确定。 - user541686
@40two valarray没有成员函数begin()end(),因此需要进行重载。 - T.C.
哦,等等,初始化列表是按值传递的。这是有意为之吗? - user541686
@T.C. 我知道,我只是提供额外信息。 - 101010
@Mehrdad 我不知道。然而,由于复制initializer_list并没有任何特殊的作用,我认为这并不是委员会决定指定额外重载的原因。 - T.C.
1个回答

11
这在N2930中有解释,该文件提议添加相关重载函数。重点是:

所提议的更改摘要

  • 指定基于范围的for语句不使用概念,使用参数相关的查找begin和end(始终包括名称空间std中的那些begin和end函数)提供序列开始和结束的迭代器。
  • 指定基于范围的for语句以使数组和初始化列表不依赖于<iterator>
  • 重新设计<initializer_list>,使其不依赖于其他头文件并且不包含其他头文件。
  • 指定应该#include <initializer_list>的库标头。

似乎他们没有解释为什么想要<initializer_list>不依赖于<iterator>,但我认为可以合理猜测,前者应该在独立实现中可用,而后者可能不是(表16,§17.6.1.3)。


嗯,我猜问题是为什么他们提供了额外的重载,而不是将<initializer_list>添加到§24.7 [iterator.range]/p1的头文件列表中。 - T.C.
4
自从该提案后,范围 for 的查找“begin”/“end”的方式已发生变化——它首先查找成员函数,因此不再需要那些重载。 - Xeo

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接