0

I have the following code:

#include <iostream>

struct Base {
    int i_;
};

class El : protected Base {
public:
    int get_i() const { return i_; }
    void set_i(int i) { i_ = i; }
};

class It : protected Base {
public:
    using pointer = const El*;
    using reference = const El&;

    reference operator*() const
    {
        return reinterpret_cast<reference>(*this);
    }

    pointer operator->() const
    {
        return reinterpret_cast<pointer>(this);
    }
};

int main()
{
    It it;
    It* itp = &it;
    std::cout << *****(itp)->get_i() << "\n"; //ERROR
}

Both GCC and Clang++ somehow fail to invoke either of operator* or operator->, so I get an error It doesn't have member function 'get_i' in the last line regardless how many indirections I try. Does the standard warrant such unintuitive behavior?

  • The `reinterpret_cast` from `It` to `El` is undefined behavior. Even if you get it to compile, there's no guarantee that the generated code will work. – Geoff Reedy Sep 07 '12 at 20:51
  • Bonus question: how to do this in a way that doesn't invoke UB? I have some data and I want to have two views of it. –  Sep 07 '12 at 20:54
  • @jons34yp: why not just make `It` derive from `El`, perhaps privately? Basically you're going out of your way (and breaking strict aliasing) just to stop someone calling `get_i()` on an `It`. But maybe in your real code, `El` has some operators that clash with those of `It`. Normally you write iterators to refer to elements rather than each element being its own iterator, so I guess something funny is going on. – Steve Jessop Sep 07 '12 at 20:57
  • In the actual code `El` is itself an iterator - it refers to data which can not be represented as an object. Anyway, thanks for suggestion, it's a good improvement. –  Sep 07 '12 at 22:07

1 Answers1

5

Operator precedence: -> binds more tightly, so is applied to the pointer itp.

When you overload operator->, that doesn't affect the meaning of operator-> applied to a pointer-to-your-class. You want (*itp)->get_i();, I think.

Steve Jessop
  • 273,490
  • 39
  • 460
  • 699