pythonic metaphor
pythonic metaphor

Reputation: 10546

Overloading operator-> when operator* returns temporary

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

Answers (1)

dyp
dyp

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

Related Questions