Implicit conversion to pointer

Viewed 80

I have this chunk of code:

struct A
{
    operator int*() { return nullptr; }
};
int main()
{
    A x;
    x[42] = 42;
    int z = x[42];
}

To my surprise, the following compiles. The implicit conversion takes place and conditionally converts A to int* and accesses the memory given by the pointer (I returned nullptr just for simplicity). As the reference says:

Implicit conversions are performed whenever an expression of some type T1 is used in context that does not accept that type, but accepts some other type T2; in particular:

  • when the expression is used as an operand with an operator that expects T2

So, why does the following not work?

struct A
{
    int operator[](int)
    {
        return 42;    
    }
};

struct B
{
    operator A()
    {
        return A();
    }
};

int main()
{
    B x;
    int z = x[42];
    x[42] = 42;
}

The compiler says: error: no match for 'operator[]' (operand types are 'B' and 'int'). What am i missing?

1 Answers

These automatic conversions are not applied before calling a member function. A nice example for this is the following

struct A {
    bool operator<(int) const {
        return true;
    }
};

bool operator>(const A &, int) {
    return false;
}

struct B {
    operator A() {
        return A();
    }
};

int main() {
    B b;
    auto z1 = b > 5;  // Works; calls operator<(B::operator A(), int)
    auto z2 = b < 5;  // Compile error; tries to call B::operator(int) which does not exist
}

You see, we defined < and > pretty similarly, but < as a member and > as a free function. For the free function the implicit conversions are done, for member functions not.

To bring this to your example int * is not an object, hence, it cannot have a member functions. So the operator[] for int * is a basically a free function (this is not exactly correct, it is more ingrained in the language. But I think it is a useful model for thinking about it). Hence, we can call operator[](A::operator int*(), int).

You cannot reproduce this behavior for object types, since operator[] cannot be defined as a free function (that's how the language is).

Related