Jarek C
Jarek C

Reputation: 1261

Unexpected template instantiation leading to a compile error

I just wonder why my code cannot be compiled. Is the below okay? I'm trying to declare a simple class with Category1 and Category2 typedef-s.

Category1 typedef compiles fine but Category2 one does not.

It seems that Category2 typedef cannot be compiled because class iterator_traits<> is instantiated despite the surrounding class X is not instantiated... Seems very confusing for me.

#include <iterator>

template <class GetterFunType>
struct X {
  GetterFunType containerGetterFun;

  // works
  typedef typename std::iterator_traits<typename GetterFunType::iterator>::iterator_category Category1;

  // compile error - std::iterator_traits<> is instantiated with type 'unknown'
  typedef typename std::iterator_traits<
    decltype(containerGetterFun().begin())>::iterator_category Category2;

  X(GetterFunType _containerGetterFun) : containerGetterFun(_containerGetterFun) { }
};

Note that I do not need to instantiate class X to get the following errors (the above is the complete compilation unit).

In Visual Studio 2012 I'm getting this:

1>c:\program files (x86)\microsoft visual studio 11.0\vc\include\xutility(364): error C2146: syntax error : missing ';' before identifier 'iterator_category'
1>          c:\data\fsl\apif_src_review\apif_src\systemns.cpp(11) : see reference to class template instantiation 'std::iterator_traits<_Iter>' being compiled
1>          with
1>          [
1>              _Iter=unknown
1>          ]
1>          c:\data\fsl\apif_src_review\apif_src\systemns.cpp(14) : see reference to class template instantiation 'X<GetterFunType>' being compiled
1>c:\program files (x86)\microsoft visual studio 11.0\vc\include\xutility(364): error C3254: 'std::iterator_traits<_Iter>' : class contains explicit override 'iterator_category' but does not derive from an interface that contains the function declaration
1>          with
1>          [
1>              _Iter=unknown
1>          ]
1>c:\program files (x86)\microsoft visual studio 11.0\vc\include\xutility(364): error C2838: 'iterator_category' : illegal qualified name in member declaration
1>c:\program files (x86)\microsoft visual studio 11.0\vc\include\xutility(364): error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
1>c:\program files (x86)\microsoft visual studio 11.0\vc\include\xutility(364): error C2602: 'std::iterator_traits<_Iter>::iterator_category' is not a member of a base class of 'std::iterator_traits<_Iter>'
1>          with
1>          [
1>              _Iter=unknown
1>          ]
1>          c:\program files (x86)\microsoft visual studio 11.0\vc\include\xutility(364) : see declaration of 'std::iterator_traits<_Iter>::iterator_category'
1>          with
1>          [
1>              _Iter=unknown
1>          ]
1>c:\program files (x86)\microsoft visual studio 11.0\vc\include\xutility(364): error C2868: 'std::iterator_traits<_Iter>::iterator_category' : illegal syntax for using-declaration; expected qualified-name
1>          with
1>          [
1>              _Iter=unknown
1>          ]

In xutility(364) there is:

template<class _Iter>
    struct iterator_traits
    {   // get traits from iterator _Iter
    typedef typename _Iter::iterator_category iterator_category;
    typedef typename _Iter::value_type value_type;
    typedef typename _Iter::difference_type difference_type;
    typedef difference_type distance_type;  // retained
    typedef typename _Iter::pointer pointer;
    typedef typename _Iter::reference reference;
    };

My case is that I want to declare a class that gets a lambda in constructor. The lambda is expected to return a reference to a container. And I need to determine wheter the returned container has a random-access iterator. But I got stuck with this compilation error. Thank you for explanation!

Upvotes: 1

Views: 930

Answers (2)

Jarek C
Jarek C

Reputation: 1261

I see that the code is okay but there are some Visual Studio 2012 limitations not allowing to compile. At least in MSVS 2015 it works, same as for gcc 5.3.1. Thanks, friends!

Upvotes: 0

Sam Varshavchik
Sam Varshavchik

Reputation: 118445

I was able to compile the same code without any errors using gcc 5.3.1, with -std=c++11

Your compiler is a relatively old compiler that does not support the current C++1x standard. Switching to another compiler is the only option I can see here, if you need to use modern C++ features.

Upvotes: 1

Related Questions