为什么在这种情况下“std :: begin()”总是返回“const_iterator”?
#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;
}
我的编译器是铛4.0。输出是:为什么在这种情况下“std :: begin()”总是返回“const_iterator”?
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>>()
导致一个rvalue表达式可以表示为:
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)是可行的 - 右值不能由约束非常量左值引用。被引用的类型的常量资格意味着,编译器将使用begin
成员函数的常量合格过载:
const_iterator begin() const noexcept;
// ~~~~^
返回const_iterator
类型的一个实例。
您可以通过从std::declval
呼叫请求的std::vector<int>
左值表达式改变这种行为:
decltype(std::begin(std::declval<std::vector<int>&>())) pos_1 = coll.begin();
// ~~^~~
有趣的是:如果已经使用了非'static'成员版本的'begin',那么可变版本将会是首选,返回'iterator'。这是成员和非成员函数不同的一种方式 – KABoissonneault
@KABoissonneault你的意思是'std :: declval
,如果你有Type&&
(临时),然后重载分辨率 会喜欢const Type&
超过Type&
,因为 暂时不会绑定到非const左值参考
我的猜测是,那是因为它是因为推导的youre的pos_1''使用临时类型。它们只绑定到const引用和所有这些,这是const在游戏中的地方。 – Borgleader