Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

Tags:

c++

iterator

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?

like image 993
Adam Avatar asked Oct 17 '18 13:10

Adam


People also ask

What is the return type of dereference operator?

In computer programming, a dereference operator, also known as an indirection operator, operates on a pointer variable. It returns the location value, or l-value in memory pointed to by the variable's value. In the C programming language, the deference operator is denoted with an asterisk (*).

Does the arrow operator dereference?

The arrow operator ( -> ) is an infix operator that dereferences a variable or a method from an object or a class. The operator has associativity that runs from left to right. This means that the operation is executed from left to right.

What does the -> operator do in C?

It is used with a pointer variable pointing to a structure or union. The arrow operator is formed by using a minus sign, followed by the greater than symbol as shown below. Operation: The -> operator in C or C++ gives the value held by variable_name to structure or union variable pointer_name.

What does the arrow operator do in C++?

The -> is called the arrow operator. It is formed by using the minus sign followed by a greater than sign. Simply saying: To access members of a structure, use the dot operator. To access members of a structure through a pointer, use the arrow operator.


2 Answers

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 InputIterators. 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.

like image 159
Yakk - Adam Nevraumont Avatar answered Sep 18 '22 00:09

Yakk - Adam Nevraumont


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.

like image 35
Sergey Kalinichenko Avatar answered Sep 21 '22 00:09

Sergey Kalinichenko