fang
fang

Reputation: 199

Ambiguous call to overloaded static function

I'm confused by this situation and googling didn't give me the answer. Basically I have the following simple code that doesn't compile:

#include <iostream>

class A
{
public:
    int a(int c = 0) { return 1; }
    static int a() { return 2; }
};

int main()
{
    std::cout << A::a() << std::endl;
    return 0;
}

In compiling this, GCC 4.2 says the call to A::a() in main() is ambiguous with both versions of a() valid candidates. Apple's LLVM compiler 3.0 compiles with no error.

Why is gcc confused about which function I want to call? I thought it was obvious that by qualifying a() with A:: I'm asking for the static version of the function. Naturally this code still doesn't compile if I remove the static function a(), because A::a() is not valid syntax for calling the non-static a().

Thanks for any comment!

Upvotes: 12

Views: 1444

Answers (2)

Johannes Schaub - litb
Johannes Schaub - litb

Reputation: 506905

The reason for this is because C++ specifies that this is ambiguous. Overload resolution specifies that for A::a, since this is not in scope, the argument list in that call is augmented by a contrived A object argument, instead of *this. Overload resolution does not exclude non-static member functions, but instead

If the argument list is augmented by a contrived object and overload resolution selects one of the non-static member functions of T, the call is ill-formed.

This has recently been subject of extensive discussion both in the committee in context of core issue 1005. See core issue 364 which considered changing this rule but didn't do so.

Upvotes: 6

Bingo
Bingo

Reputation: 3833

The reason is name resolution happens before anything else the compiler does, like figuring out which overloaded function to use.

Qualifying the function with A:: simply tells the compiler to "look inside of A to find the name a". It doesn't actually help resolve which function you are referring to.

EDIT

And so when you type A::a(), first the compiler thinks "look in A for a member function or member who can use operator()".

Then the compiler thinks, "Ok, two possibilities here, which one is being referred to? a() or a(int c = 0) with a default c=0. Not sure.

If you removed the static keyword and called the functions like obj.a(), there would still be an ambiguity.

WRT LLVM's parser

I would say that it does some extra work for you, which is not required by the standard, which would be to assume A::a() is static.

Upvotes: 3

Related Questions