tags:

views:

75

answers:

3

I'm trying to compile code from an open source project, and I'm running into a problem where gcc claims that a particular line of code has an ambiguous interpretation. The problem involves a templated class and these two methods:

template <class X>
class A {
public:
    X& operator[] (int i) { ... }
    operator const X* () { ... }
};

When this is used along the lines of this:

A<B*> a;
B* b = a[i];

gcc complains about the ambiguous resolution of a[i]. The problem is made more clear by replacing the definition of A with its specific instantiation:

class A_B {
public:
    B*& operator[] (int i) { ... }
    operator B* const * () { ... }
};

The problem is that there are two ways of interpreting B* b = a[i]:

// First interpretation (array-like behaviour first)
B*& b1 = a[i];
B* b2 = (B*) b1;

// Second interpretation (casting behaviour first)
B* const * b1 = (B* const *) a;
B* b2 = b1[a];

My question is this: Is there some way to provide a preferred interpretation, preferably by making the casting version undesirable without an explicit cast, so that I don't have to modify every line that tries to invoke A[]? I realize that the interpretation is legitimately ambiguous, but I know what the intention of the code is, and I would like to communicate that to the compiler with minimal changes.

Edit: It seems my example doesn't cause the bug in question, so I'm not correctly summarizing the original code, nor correctly identifying the problem. I'll try to get an example that produces the problem first, sorry folks.

+2  A: 

You could use braces:

A<B*> a;
B* b = (a[i]); // Now it must evaluate the sub-expression a[i]

NB. Your example above compiles fine and calls the operator[] as expected.

Martin York
+2  A: 

The following code compiles for me with g++ 3.x. I don't think your analysis of the problem is correct, but in any case could you post the error message you are getting.

template <class X>
struct A {
    X& operator[] (int i) { static X x; return x; }
    operator const X* () { return 0; }
};

class B {};

int main() {
    A<B*> a;
    B* b = a[0];
}
anon
A: 

You can force compiler to bind to operator [ ] by this:

B* b = a::operator [ ] ( 0 );

But anyway, defining conversions is always a bad idea. I would search every other way around it before resorting to conversion operators.

Tanveer Badar