为什么在这种情况下 "std::begin()" 总是 return "const_iterator"?
Why does "std::begin()" always return "const_iterator" in such a case?
#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()
总是 return const_iterator
而不是 iterator
?
如果你有 Type&&
(临时的)那么重载解析
将更喜欢 const Type&
而不是 Type&
,因为
临时不会绑定到非常量左值引用
函数调用:
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 限定意味着编译器将使用 begin
成员函数的 const 限定重载:
const_iterator begin() const noexcept;
// ~~~~^
其中 returns 类型的实例 const_iterator
.
您可以通过从 std::declval
调用中请求 std::vector<int>
的左值表达式来更改该行为:
decltype(std::begin(std::declval<std::vector<int>&>())) pos_1 = coll.begin();
// ~~^~~
#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()
总是 return const_iterator
而不是 iterator
?
如果你有 Type&&
(临时的)那么重载解析
将更喜欢 const Type&
而不是 Type&
,因为
临时不会绑定到非常量左值引用
函数调用:
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 限定意味着编译器将使用 begin
成员函数的 const 限定重载:
const_iterator begin() const noexcept;
// ~~~~^
其中 returns 类型的实例 const_iterator
.
您可以通过从 std::declval
调用中请求 std::vector<int>
的左值表达式来更改该行为:
decltype(std::begin(std::declval<std::vector<int>&>())) pos_1 = coll.begin();
// ~~^~~