Reputation: 1593
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);
^
Upvotes: 0
Views: 1010
Reputation: 96800
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}; // ^^^^^^^^^^^^^^^^^^^^^^^^
Upvotes: 2