c++ - 为什么 "std::begin()"在这种情况下总是返回 "const_iterator"?

标签 c++ c++11 iterator standards type-safety

#include <vector>
#include <iostream>

using namespace std;

int main()
{
    vector<int> coll;

    decltype(std::begin(std::declval<vector<int>>()))
        pos_1 = coll.begin();
    auto pos_2 = coll.begin();

    cout << typeid(decltype(pos_1)).name() << endl;
    cout << typeid(decltype(pos_2)).name() << endl;
}

我的编译器是 clang 4.0。输出是:

class std::_Vector_const_iterator<class std::_Vector_val<struct std::_Simple_types<int> > >
class std::_Vector_iterator<class std::_Vector_val<struct std::_Simple_types<int> > >

也就是说:pos_1 = pos_2; 可以,而pos_2 = pos_1; 不行。

为什么在这种情况下 std::begin() 总是返回 const_iterator 而不是 iterator

最佳答案

函数调用:

std::declval<std::vector<int>>()

产生一个右值表达式,可以表示为:

std::vector<int>&&

编译器有两个(通用)重载 std::begin可供选择([iterator.range]):

template <class C> 
auto begin(C& c) -> decltype(c.begin());        // #1

template <class C> 
auto begin(const C& c) -> decltype(c.begin());  // #2

对于右值表达式,只有第二个重载 (#2) 是可行的——右值不能被非 const 左值引用绑定(bind)。引用类型的 const 限定意味着编译器将使用 begin 的 const 限定重载。成员函数:

const_iterator begin() const noexcept;
//                     ~~~~^

返回 const_iterator 类型的实例.

您可以通过请求 std::vector<int> 的左值表达式来更改该行为。来自 std::declval调用:

decltype(std::begin(std::declval<std::vector<int>&>())) pos_1 = coll.begin();
//                                             ~~^~~      

关于c++ - 为什么 "std::begin()"在这种情况下总是返回 "const_iterator"?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42580761/

相关文章:

c++ - boost 函数映射到字符串

c++ - 使用 std::shared_ptr 对象实例创建 boost::thread

C++ STL,常量迭代器,find()

python - 迭代器协议(protocol)。是黑魔法吗?

c++ - 保护程序中的 C++ 代码

c++ - Qt 中的项目未在 TreeView 中排序

java - JNI 和 C++ - UnsatisfiedLinkError

c++ - 使用 RAII 嵌套异常

c++ - 什么时候可以在初始化列表中省略外括号?

C++ 打印集合列表