【问题标题】:Why does "std::begin()" always return "const_iterator" in such a case?为什么在这种情况下“std::begin()”总是返回“const_iterator”?
【发布时间】:2017-07-23 16:11:29
【问题描述】:
#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

【问题讨论】:

  • 我猜这是因为你使用临时推断pos_1 的类型。它们只绑定到 const 引用和所有这些,这就是 const 发挥作用的地方。

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


【解决方案1】:

函数调用:

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 左值引用绑定。引用类型的 const 限定意味着编译器将使用 begin 成员函数的 const 限定重载:

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

返回一个const_iterator类型的实例。

您可以通过从std::declval 调用中请求std::vector&lt;int&gt; 的左值表达式来更改该行为:

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

【讨论】:

  • 有趣的是:如果使用了begin 的非static 成员版本,则首选可变版本,返回iterator。这是成员函数和非成员函数不同的一种方式
  • @KABoissonneault 你的意思是std::declval&lt;std::vector&lt;int&gt;&gt;().begin()?是的,那是因为[over.match.funcs]/p5.1
【解决方案2】:

如果你有Type&amp;&amp;(一个临时的)然后重载解析 会更喜欢const Type&amp; 而不是Type&amp;,因为 临时不会绑定到非 const 左值引用

【讨论】:

    猜你喜欢
    • 2016-03-02
    • 2014-09-12
    • 2018-04-26
    • 2018-05-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多