u carcamagnu
u carcamagnu

Reputation: 43

MSVC 2015 - compiler error in std::for_each for custom iterator (only when in DEBUG)

I've implemented a custom container class together with its iterator, and trying to use a for_each on it. Everything compiles fine in VC6, online cpp.sh and MSVC15, the latter only in release: when in debug I got a series of errors I report, under, the oversimplified version of my code.

struct Functor {
  void operator()(int&) {}
} func;

struct Container {
  typedef int value_type;
  struct iterator {
    bool operator!=(iterator const&) { return true; }
    iterator& operator++() { return *this; }
    value_type& operator*() { return i; } //this is just to compile, not for real
    int i; //this is just to compile, not for real
  };
  iterator begin() { return iterator(); }
  iterator end() { return iterator(); }
};

#include <algorithm>
int main() {
  Container c;
  std::for_each(c.begin(), c.end(), func);  // compile errors
  return 0;
}

Errors:

1>c:\program files\microsoft visual studio 14.0\vc\include\xutility(838): error C2672: '_Iter_cat': no matching overloaded function found
1>  c:\program files\microsoft visual studio 14.0\vc\include\algorithm(31): note: see reference to function template instantiation 'void std::_Debug_range_ptr<_InIt,_Fn1>(_InIt,_InIt,_Pty &,std::_Dbfile_t,std::_Dbline_t)' being compiled
1>          with
1>          [
1>              _InIt=Container::iterator,
1>              _Fn1=Functor,
1>              _Pty=Functor
1>          ]
1>  [...]: note: see reference to function template instantiation '_Fn1 std::for_each<Container::iterator,Functor>(_InIt,_InIt,_Fn1)' being compiled
1>          with
1>          [
1>              _Fn1=Functor,
1>              _InIt=Container::iterator
1>          ]
1>c:\program files\microsoft visual studio 14.0\vc\include\xutility(838): error C2893: Failed to specialize function template 'iterator_traits<_Iter>::iterator_category std::_Iter_cat(const _Iter &)'
1>  c:\program files\microsoft visual studio 14.0\vc\include\xutility(838): note: With the following template arguments:
1>  c:\program files\microsoft visual studio 14.0\vc\include\xutility(838): note: '_Iter=Container::iterator'
1>c:\program files\microsoft visual studio 14.0\vc\include\xutility(838): error C2672: '_Debug_range_ptr2': no matching overloaded function found
1>c:\program files\microsoft visual studio 14.0\vc\include\xutility(838): error C2780: 'void std::_Debug_range_ptr2(_RanIt,_RanIt,_Pty &,std::_Dbfile_t,std::_Dbline_t,std::random_access_iterator_tag)': expects 6 arguments - 5 provided
1>  c:\program files\microsoft visual studio 14.0\vc\include\xutility(820): note: see declaration of 'std::_Debug_range_ptr2'
1>c:\program files\microsoft visual studio 14.0\vc\include\xutility(838): error C2780: 'void std::_Debug_range_ptr2(_InIt,_InIt,_Pty &,std::_Dbfile_t,std::_Dbline_t,std::input_iterator_tag)': expects 6 arguments - 5 provided
1>  c:\program files\microsoft visual studio 14.0\vc\include\xutility(811): note: see declaration of 'std::_Debug_range_ptr2'

Upvotes: 3

Views: 1221

Answers (2)

Niall
Niall

Reputation: 30614

MSVC has more extensive debug checks when using iterators. Presumably this requires a more complete definition of the iterator with all its embedded types.

Traditionally iterators have been derived from std::iterator<> that provides default definitions for the embedded types required.

template< 
    class Category,
    class T,
    class Distance = std::ptrdiff_t,
    class Pointer = T*,
    class Reference = T& 
> struct iterator;

A change to the code as follows should clear things up;

  struct iterator : std::iterator<
    std::input_iterator_tag, // or as required
    int
  >

Upvotes: 2

Vlad from Moscow
Vlad from Moscow

Reputation: 311088

Usually iterators are defined as derived classes of the standard class std::iterator that is declared like

template<class Category, class T, class Distance = ptrdiff_t,
class Pointer = T*, class Reference = T&> struct iterator;

One of its template parameters is Category that determinates the category tag of the iterator such as for example std::input_iterator_tag.

In the debug mode the compiler performs some checks based on the category of the iterator.

You should follow this standard model of defining iterators.

Upvotes: 0

Related Questions