Reputation: 10546
I have two classes with the following structure:
struct A {
A transform() const;
};
struct B {
// returns a temporary A
A operator*() const;
};
The *
operator may look a little weird here, but given the context of its usage is actually pretty natural. In fact, B
really exists only to provide some syntatic sugar for an embedded language, so it's methods and operators are designed to give desired look to code. Given B b
, getting the associated A
is fast, *b
. I sometimes want to call the transform on A
immediately. Currently, this requires some extra parentheses (*b).transform()
. There seems like a natural simplification, namely b->transform()
. But operator ->
is supposed to return a pointer and operator *
is returns a temporary. How can I implement an overload like that?
Upvotes: 4
Views: 120
Reputation: 39121
Disclaimer: I'm not responsible for any confusions that arise from changing the value category of the overloaded operators from their built-in counterparts.
struct just_some_type
{
int m;
int transform() { return m; }
};
// the intermediate helper stops the recurring application of ->
// if the lhs of -> is of a class type
struct intermediate_helper
{
just_some_type member;
just_some_type* operator->() { return &member; }
};
struct ptr_like
{
just_some_type operator*()
{ return {42}; }
intermediate_helper operator->()
{ return {{42}}; }
};
Usage example:
#include <iostream>
int main()
{
auto p = ptr_like{};
std::cout << (*p).transform() << "\n";
std::cout << p->transform() << "\n";
}
Important note: the object acted upon in p->
is an lvalue, as the built-in ->
is applied to a pointer! E.g. if you qualify transform
with an lvalue-ref like int transform() &;
, then the version (*p).transform()
will fail to compile, but p->transform()
still is legal.
Upvotes: 5