Оператор разыменования структуры (оператор-›)

Я пишу тонкую оболочку шаблона для итераторов и сталкиваюсь с камнем преткновения при прохождении через оператор разыменования структуры, в основном потому, что указатели его не имеют:

#include <vector>

struct mystruct {
    int member;
};

template<class iterator>
struct wrap {
   typedef typename std::iterator_traits<iterator>::pointer pointer;
   iterator internal;
   pointer operator->() {return internal.operator->();} //MARK1
};

int main() {
    wrap<std::vector<mystruct>::iterator> a;
    a->member;
    wrap<mystruct*> b;
    b->member;
    return 0;
}

http://ideone.com/XdvEz

prog.cpp: In member function ‘typename std::iterator_traits<_Iter>::pointer wrap<iterator>::operator->() [with iterator = mystruct*]’:
prog.cpp:18:   instantiated from here
prog.cpp:11: error: request for member ‘operator->’ in ‘((wrap<mystruct*>*)this)->wrap<mystruct*>::internal’, which is of non-class type ‘mystruct*’

Этот следующий метод работает, но я не думаю, что он гарантированно сработает. А именно, если итератор имеет странный тип pointer, который не совпадает с указателем на value_type.

   pointer operator->() {return &*internal;} //MARK3

person Mooing Duck    schedule 16.12.2011    source источник
comment
В какой версии C++ есть оператор разыменования структуры?   -  person Thomas Matthews    schedule 16.12.2011
comment
Почему char*? А не будет ли где-нибудь Iterator::value_type?   -  person Kerrek SB    schedule 16.12.2011
comment
@ThomasMatthews: так это называется Википедия. Стандарт С++ просто называет это operator->.   -  person Mooing Duck    schedule 16.12.2011
comment
Я не понимаю, что вы хотите вернуть - ссылку на объект, или итератор, или указатель на объект? Да, пишите не псевдокод, а минимальный репрезентативный код.   -  person Kerrek SB    schedule 16.12.2011
comment
Разве специализация шаблона не будет правильным способом сделать это?   -  person lapk    schedule 16.12.2011
comment
@KerrekSB: заменено char на mystruct, у которого есть член. Теперь вопрос должен иметь смысл. Я не понимал, что это не имеет смысла, потому что IDEone выдавал ожидаемое сообщение об ошибке.   -  person Mooing Duck    schedule 16.12.2011
comment
@AzzA: Если требуется специализация шаблона, это вариант, но я чувствую, что должен быть способ сделать это.   -  person Mooing Duck    schedule 16.12.2011
comment
@Thomas Matthews Я рад, что обнаружил термин оператор разыменования структуры, поскольку «-›» невозможно найти в Google для: P.   -  person Daniel Buckmaster    schedule 01.01.2012
comment
@AzzA: Как оказалось, я выбрал специализацию, так как мне нужен был однородный возвращаемый тип.   -  person Mooing Duck    schedule 09.01.2012


Ответы (1)


В стандарте косвенно говорится, что перегруженный operator-> должен возвращать либо указатель, либо объект, преобразуемый в указатель, либо объект, который имеет перегруженный operator->. Лучше всего просто вернуть internal.

§13.5.6 [over.ref] p1

Выражение x->m интерпретируется как (x.operator->())->m

(Вышеприведенное применяется рекурсивно.)

person Xeo    schedule 16.12.2011
comment
И прежде чем вы спросите о operator*(), тип возвращаемого значения — iterator_traits<iterator>::reference и возвращает только *iterator. Любой итератор, который не возвращает reference при разыменовании, неправильно моделирует концепцию итератора и может быть безопасно проигнорирован. - person Xeo; 17.12.2011
comment
Да, я получил operator*, но мне никогда не приходило в голову вернуть iterator вместо pointer. Спасибо! Я ожидаю, что это ответ, но я постараюсь дать ему день или около того для других предложений. - person Mooing Duck; 17.12.2011
comment
Я бы просто добавил, что рекурсия заканчивается, когда возвращается указатель (или объект, преобразуемый в указатель), поэтому, если оператор-> возвращает указатель, вы попали в базовый случай рекурсии, и все готово. Если оператор-> возвращает что-то еще с перегрузкой оператора->, вы рекурсивно. Это может показаться очевидным, но мне потребовалось некоторое время, чтобы разобраться. - person Pete Baughman; 17.09.2013