非成员函数 begin()/cbegin() 及其constexpr-ness

non-member function begin()/cbegin() and its constexpr-ness

C++11 引入了没有 constexpr-说明符的 std::begin() 非成员函数,然后 C++14 更新为 constexpr-std::begin() for array type(T (&)[N]) 并为通用容器类型 (const C&).

附加 constexpr-std::cbegin()

引自http://en.cppreference.com/w/cpp/iterator/begin

template< class T, size_t N >
constexpr T* begin( T (&array)[N] );  // (since C++14)

template< class C >
constexpr auto cbegin( const C& c ) -> decltype(std::begin(c));  // (since C++14)

因此我们可以在 constexpr 上下文中使用 std::begin() and/or std::cbegin() 用于原始数组类型 T[N](对于 C++14 constexpr 函数)。

问题:

  1. C++14 不允许在 "Standard Containers" 的 constexpr 上下文中使用非成员 std::begin(),例如 std::array,因为它们不提供 constexpr-begin()成员函数。我的解释正确吗?
  2. 为什么非成员 std::cbegin()constexpr-说明符?对于用户提供的具有 constexpr-begin() 成员函数的容器?

标准库中当前的 constexpr 支持确实相当有限。

  1. 非成员 std::begin 未标记为 constexpr 因为除了 arrayinitializer-list 之外,没有标准容器(或类似实体的容器,例如 bitset)支持 constexpr成员begin()(主要是因为一些实现想使用动态内存分配来使用迭代器调试)。你在这里的解释是正确的。
  2. 非成员 std::cbegin 被标记为 constexpr 以支持(当前)两个 constexpr std::begin 非成员函数 arrayinitializer_list,并向前兼容标准库中的未来升级。

关于第 2 点,它对于像实体这样的用户定义容器不是很有用,因为那里公认的习惯用法是在围绕用户定义的类型,而不是 namespace std.