нет типа с именем «указатель» в структуре std :: iterator_traits & lt; … & gt;

Вот фрагменты моего шаблона connected_list:

#include <iostream>
#include <iterator>

template < class >
struct linked_list {
struct iterator_base : public std::iterator< std::bidirectional_iterator_tag , int >
{
typename std::iterator_traits< iterator_base >::pointer operator -> () const {
std::cerr << __func__ ;
return nullptr ; } ;
};
using difference_type = typename std::iterator_traits< iterator_base >::difference_type ;
} ;

int main ()
{
int * inullptr = linked_list< int >::iterator_base().operator->() ;
return 0 ;
}

Когда я уйду using... строка без комментариев, код не компилируется.

g ++ 5.4:

list2.cxx:105:66: error: no type named ‘pointer’ in ‘struct std::iterator_traits<linked_list<int>::iterator_base<(linked_list<int, std::allocator<int> >::constantness)1u> >’
typename std::iterator_traits< iterator_base >::pointer operator -> () const { return &( to_obj_node( current_node_ ) -> object() ) ; }

icpc:

list.cxx(105): error: incomplete type is not allowed typename std::iterator_traits< iterator_base >::pointer operator -> () const { return &( to_obj_node( current_node_ ) -> object() ) ; }

Без этой строки все компилируется нормально.

вопрос: что происходит, когда я комментирую using difference_type = typename std::iterator_traits< iterator >::difference_type; в приведенном выше коде (только с такими изменениями код компилируется).

================================================== ========================
res.on.functions / 2.5

  1. В частности, эффекты не определены в следующих случаях: …
    1. если неполный тип ([basic.types]) используется в качестве аргумента шаблона при создании экземпляра компонента шаблона, если не указано иное
      разрешено для этого компонента.

и исторический обсуждение на что.

0

Решение

Ошибка здесь в том, что тип std::iterator_traits< iterator_base > все еще неполный и в то время, когда вы хотите получить доступ ::pointer еще не предусматривает, что pointer член.

Класс std::iterator_traits<iterator_base> создается в typename std::iterator_traits< iterator_base >::difference_typeпотому что он используется на левой стороне ::и потому что он еще не был создан. Это запускает создание linked_list<int>::iterator_base потому что тело iterator_traits использует этот класс для определения его различных членов typedefs — например, создание экземпляра может происходить в строке, которая выглядит как typedef typename Iterator::value_type value_type; в стандартной библиотеке.

Далее следует использование std::iterator_traits< iterator_base >::pointer в вашем вложенном классе. Этот раз, iterator_traits<iterator_base> уже создается, так что ничего не делается, и ::pointer ищется. Но так как это еще не было объявлено, оно не может быть найдено.

Обратите внимание, что когда вы закомментируете using строка, ничто в коде больше не будет создавать экземпляр вложенного тела класса (тело членов шаблонов классов «лениво создается»), так что это не может быть мерой за или против валидности конструкций внутри этого вложенного тела класса ,

1

Другие решения

#include <iterator>

struct OK_1: std::iterator<std::bidirectional_iterator_tag, int> {};
using Pointer_1 = typename std::iterator_traits<OK_1>::pointer;

struct Nah
{
using Pointer_nah = typename std::iterator_traits<Nah>::pointer;    //!
};

auto main() -> int
{}

На момент объявления Pointer_nahтип Nah является неполным типом.

iterator_traits должен заглянуть внутрь этого типа, чтобы найти его pointer определение.

Но это, рекурсивно, требует определения iterator_traits<Nah>,

И так далее.

Но главное: Nah является неполным в точке, где Pointer_nah объявлен незавершенный означает, что класс не полностью известен. В частности, его размер здесь не известен, поэтому его нельзя передать sizeof,

Я подозреваю, что это причина, по которой один из ваших компиляторов воскликнул:

» ошибка: неполный тип не допускается

0

По вопросам рекламы [email protected]