Question

I am working my way through the 4th edition of Bjarne Stroustrup's C++ book and have run into a problem with iterator categories. Here is a snippet of code copied essentially directly from the book that does not compile (chapter 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;
}

If I comment out the contents of the helper function that uses the forward iterator tag, everything compiles and works perfectly. If comment out the contents of the function, but replace the decltype with

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

that will compile, but then compilation breaks as soon as I try to include the sort because if I don't de-reference beg, the sort is trying to operate on forward iterators. If I include the de-ref, the error spew is hard to parse, but it looks like the compiler is trying to treat the argument as a pointer to an int and it is complaining about const violations and the like.

Can anyone offer any insight?

Edit: Here is the first error from the compiler error spew:

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);
        ^
Was it helpful?

Solution

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

*beg returns a reference to the value_type object of the vector. You're getting an error because you can't use a vector of references.

You can use std::remove_reference to discard the references, or you can utilize the exposed value_type member from the iterator type:

std::vector<typename For::value_type> v{beg, end};
//          ^^^^^^^^^^^^^^^^^^^^^^^^
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top