【问题标题】:iterator_category and decltypeiterator_category 和 decltype
【发布时间】:2014-02-24 05:31:24
【问题描述】:

我正在阅读 Bjarne Stroustrup 的 C++ 书籍的第 4 版,但遇到了迭代器类别的问题。这是一段基本上直接从书中复制的代码的 sn-p 代码,但未编译(第 5.4.2.1 章):

#include <algorithm>
#include <iostream>
#include <vector>
#include <forward_list>
#include <iterator>
#include <string>

template<typename Ran>   // for random access iterators
void sort_helper(Ran beg, Ran end, std::random_access_iterator_tag) {
  std::sort(beg, end);
}

template<typename For>   // for forward access iterators
void sort_helper(For beg, For end, std::forward_iterator_tag) {
  std::vector<decltype(*beg)> v{beg,end}; // compilation fails here
  std::sort(v.begin(),v.end());
  std::copy(v.begin(),v.end(),beg);
}

template<typename C>
using Iterator_type = typename C::iterator;

template<typename Iter>
using Iterator_category = typename std::iterator_traits<Iter>::iterator_category;

template<typename C>
void sort(C& c) {
  using Iter = Iterator_type<C>;
  sort_helper(c.begin(), c.end(), Iterator_category<Iter>());
}

void test(std::vector<std::string>& v, std::forward_list<int>& lst) {
  sort(v);
  std::sort(v.begin(),v.end());
  sort(lst);
}

int main(int argc, char * argv[]) {
  std::vector<std::string> sv {"c","b","d","a"};
  std::forward_list<int> fli {3,6,1,7,2,9,4};
  test(sv,fli);
  return 0;
}

如果我注释掉使用前向迭代器标记的辅助函数的内容,一切都会编译并完美运行。如果把函数的内容注释掉,但是把decltype替换成

std::vector<decltype(beg)> v{beg,end};

这将编译,但是一旦我尝试包含排序,编译就会中断,因为如果我不取消引用请求,排序会尝试对前向迭代器进行操作。如果我包含 de-ref,则错误喷吐很难解析,但看起来编译器正试图将参数视为指向 int 的指针,并且它正在抱怨 const 违规等。

谁能提供任何见解?

编辑:这是编译器错误喷出的第一个错误:

In file included from small_utils2.cpp:1:
In file included from /usr/bin/../lib/c++/v1/algorithm:594:
/usr/bin/../lib/c++/v1/memory:1656:16: error: 'pointer' declared as a pointer to a reference of type 'int &'
    typedef _Tp*              pointer;
               ^
/usr/bin/../lib/c++/v1/memory:1448:22: note: in instantiation of template class 'std::__1::allocator<int &>' requested here
    typedef typename allocator_type::value_type value_type;
                     ^
/usr/bin/../lib/c++/v1/vector:330:22: note: in instantiation of template class 'std::__1::allocator_traits<std::__1::allocator<int &> >' requested here
    typedef typename __alloc_traits::size_type       size_type;
                     ^
/usr/bin/../lib/c++/v1/vector:484:15: note: in instantiation of template class 'std::__1::__vector_base<int &, std::__1::allocator<int &> >' requested here
    : private __vector_base<_Tp, _Allocator>
              ^
small_utils2.cpp:22:30: note: in instantiation of template class 'std::__1::vector<int &, std::__1::allocator<int &> >' requested here
        std::vector<decltype(*beg)> v{beg,end};
                                    ^
small_utils2.cpp:37:2: note: in instantiation of function template specialization 'sort_helper<std::__1::__forward_list_iterator<std::__1::__forward_list_node<int, void *> *> >' requested here
        sort_helper(c.begin(), c.end(), Iterator_category<Iter>());
        ^
small_utils2.cpp:45:2: note: in instantiation of function template specialization 'sort<std::__1::forward_list<int, std::__1::allocator<int> > >' requested here
        sort(lst);
        ^

【问题讨论】:

  • 什么是编译器错误?
  • 它有 184 行长,所以我希望有人可以复制并粘贴代码(我猜我应该提供#includes)。这里有一些亮点......嗯,我无法在看到的评论中按“enter”。

标签: c++ c++11 iterator decltype


【解决方案1】:
std::vector<decltype(*beg)> v{beg,end};

*beg 返回对向量的value_type 对象的引用。您收到错误是因为您不能使用引用向量。

您可以使用std::remove_reference 丢弃引用,或者您可以使用迭代器类型中暴露的value_type 成员:

std::vector<typename For::value_type> v{beg, end};
//          ^^^^^^^^^^^^^^^^^^^^^^^^

【讨论】:

  • 太好了,这很好用。好吧,看起来我的 Mac 上的 stdlibc++ 中的 std::remove_reference 可能存在问题,但您的回答在这两个方面都很有意义。为什么 Stroustrup 会提出他所做的呢?
  • @GabrielPerdue:他因示例的草率而臭名昭著。
  • @GabrielPerdue Bjarne 以在他的示例中出现一些小问题而闻名。 :)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-03-07
  • 1970-01-01
  • 2013-07-10
  • 1970-01-01
  • 1970-01-01
  • 2011-10-15
相关资源
最近更新 更多