Мне просто интересно, почему мой код не может быть скомпилирован. С нижним окей все в порядке? Я пытаюсь объявить простой класс с Type1 и Category2 typedef-s.
Категория1 typedef компилируется нормально, а Категория2 — нет.
Кажется, что Type2 typedef не может быть скомпилирован, потому что класс iterator_traits<> Создается экземпляр, несмотря на то, что окружающий класс X не создается … Кажется, меня очень смущает.
#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) { }
};
Обратите внимание, что мне не нужно создавать экземпляр класса X для получения следующих ошибок (выше приведен полный блок компиляции).
В Visual Studio 2012 я получаю это:
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> ]
В xutility (364) есть:
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;
};
В моем случае я хочу объявить класс, который получает лямбда-конструктор. Ожидается, что лямбда вернет ссылку на контейнер. И мне нужно определить, есть ли в возвращаемом контейнере итератор с произвольным доступом. Но я застрял с этой ошибкой компиляции. Спасибо за объяснение!
Мне удалось скомпилировать тот же код без каких-либо ошибок, используя gcc 5.3.1, с -std = c ++ 11
Ваш компилятор является относительно старым компилятором, который не поддерживает текущий стандарт C ++ 1x. Переключение на другой компилятор — единственная опция, которую я вижу здесь, если вам нужно использовать современные функции C ++.
Я вижу, что код в порядке, но есть некоторые ограничения Visual Studio 2012, не позволяющие компилировать. По крайней мере, в MSVS 2015 он работает так же, как и для gcc 5.3.1. Спасибо, друзья!