简体   繁体   中英

arrow operator (operator->) return type when dereference (operator*) returns by value

I'm writing an InputIterator, which implements, among others, operator* and operator->.

My operator* returns a pair of references to (vector) elements. Operator* returns by value therefore.

According to cppreference:

The overload of operator -> must either return a raw pointer, or return an object (by reference or by value) for which operator -> is in turn overloaded.

What do I return then?

I cannot return a raw pointer; the pair has to be returned physically somehow. So possibly some wrapper with operator-> defined? Does it exist in standard library, or how is it generally done?

template<class T>
struct fake_ptr_with_value {
  T t;
  T* operator->() { return std::addressof(t); }
};

return a fake_ptr_with_value<decltype(**this)> .

No such helper type is exposed from std .

Please note that due to defects in the specifications of what various iterator classes require, this is only usable for InputIterator s. Forward iterators (and all more powerful iterators, like random access iterators), under the standard, require that operator* return a reference to a true and stable object.

The defect is that the standard (a) in some cases requires references when pseudo-references would do, (b) mixes "iteration" and "dereference" semantics.

Rangesv3 has a more decoupled iterator category system that addresses some, if not all, of these defects.

As this question is about input iterators, this solution is sufficient; I am just including this caution in case someone wants to use this technique elsewhere. Your code may compile and seem to work, but you are almost certainly going to be violating the requirements of the C++ standard when you pass your iterator to any std function, which means your program is ill-formed no diagnostic required.

Since -> will continue "drilling down" until it hits a pointer return type , your code could return a "proxy" for the pair with the pair embedded in it:

template<class T1, class T2>
class pair_proxy {
    std::pair<T1,T2> p;
public:
    pair_proxy(const std::pair<T1,T2>& p) : p(p) {}
    std::pair<T1,T2>* operator->() { return &p; }
};

Note: I would strongly consider embedding std::pair in your iterator, and returning a pointer to it from your operator ->() implementation.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM