Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

operator-> repeats until it returns a value of non-class type

According to 13.3.1.2/8, or better footnote-129 (emphasis mine):

[...] The process repeats until an operator-> function returns a value of non-class type.

I thought I knew how operator-> works (let me say, its recursive way based on the return type), but I see that I'm completely unaware about how it actually works (I mean, its return type).

When I found it, I wondered if one can really define and use something like a double operator->() for a generic struct S, for I've never used such an operator this way.
As an example, consider the code below:

struct S { 
    constexpr double operator->() noexcept {
        return 3.14;
    }
};

int main() {
    static_assert(3.14 == S{}.operator->(), "!");
}

The syntax is quite ugly and I cannot see any use of such an operator or a similar one.

What is the real purpose of letting the programmers return a double or a float from this operator?
What could be a possible use for them?

like image 228
skypjack Avatar asked Mar 13 '23 01:03

skypjack


2 Answers

The use for operator overloads is always questionable, and should be mostly consistent with the behavior of operators as seen with the intrinsic types.

Thus the overloading of the dereferencing operators -> and unary * should behave like they are used with pointers:

Citing from Operator overloading:

Operators for Pointer-like Types

For defining your own iterators or smart pointers, you have to overload the unary prefix dereference operator * and the binary infix pointer member access operator ->:

class my_ptr {
        value_type& operator*();
  const value_type& operator*() const;
        value_type* operator->();
  const value_type* operator->() const;
};

Note that these, too, will almost always need both a const and a non-const version. For the -> operator value_type must be of class (or struct or union) type, otherwise their implementation results in a compile-time error.1

The unary address-of operator should never be overloaded.

For operator->*() see this question. It's rarely used and thus rarely ever > overloaded. In fact, even iterators do not overload it.


Obviously you can do that overload with double as return type, but that's no different from possible (non-sensical, less useful) overloads for other standard operators like e.g.

#include <type_traits>

struct S { 
    constexpr double operator->() noexcept {
        return 3.14;
    }
    void operator=(const S& rhs) {}
 // ^^^^
    void operator<(const S& rhs) {}
 // ^^^^
};

Demo

int main() {
    static_assert(3.14 == S{}.operator->(), "!");
}

Your cite

[...] The process repeats until an operator-> function returns a value of non-class type.

merely means that the dereferencing operation will stop as soon a non-class type is received as return type. Thus returning an intrinsic type will stop calling the dereference operation.
If a pointer is returned, or another type that overloads -> that operator will be called automatically upon the returned type.


1Not so sure if this statement is actually valid, my and OPs example seems to prove otherwise.

like image 168
πάντα ῥεῖ Avatar answered Mar 24 '23 20:03

πάντα ῥεῖ


What is the real purpose of letting the programmers return a double or a float from this operator?
What could be a possible use for them?

It works nicely with std::map::iterator. You can use:

std::map<int, int> m = { ... };

...

auto it  = m.find(10);
if ( it != m.end() )
{
   int val = iter->second;
}
like image 21
R Sahu Avatar answered Mar 24 '23 20:03

R Sahu