3
void g(int& a)
{
    std::cout<<"int&\n";
} 

void g(int a)
{
    std::cout<<"int\n";
}  

int main()
{    
    int a = 2;   
    g(a); //won't compile (at least under MSVC 2012)

    std::cin.ignore();
}

Is there a way to avoid ambiguous call error here ? something like g( static_cast<int&>(a) );

2
  • 2
    Which one do you want it to call? Commented Nov 13, 2012 at 20:46
  • with g( static_cast<int&>(a) ); I expected g(int& a) be called Commented Nov 13, 2012 at 20:49

3 Answers 3

10

If you can cast, there is, of course a way to disambiguate the call:

g(const_cast<int const&>(a));

If you insist to call the reference version, the resolution is a bit more tricky:

static_cast<void(*)(int&)>(g)(a);
Sign up to request clarification or add additional context in comments.

8 Comments

+1 for the cast to const (I didn't even think of that!), but -1 for using static_cast instead of const_cast, and in sum, 0. ;-)
@Cheersandhth.-Alf: Good point: I shall fix the answer to use the correct cast!
static_cast<void(*)(int&)>(g)(a);: You've got to love a language as simple as C++ :) (+1)
Ahh, exciting - then static_cast<int&&>(a) should also work, non?
Yes, for int it would. If the type isn't an int but, e.g., a std::string this use would move the object which may not entirely what you want.
|
3

This answer relates to the question as it was when I answered.

The OP keeps adding to the question, and I'm not going to chase that…


Yes there is, and yes, you're right that it involves casting to resolve the ambiguity:

#include <iostream>

void g(int& a)
{
    std::cout<<"int&\n";
} 

void g(int a)
{
    std::cout<<"int\n";
}  

int main()
{    
    int a = 2;   
    static_cast< void(*)(int&) >( g )( a );
}

Note: to run this in Visual Studio and see the result window, either use [Ctrl F5], or place a breakpoint on the last right brace of main and run it in the debugger. But better, just run it from the command line. No need to add a “stop” at the end! :-)


AMENDMENT: Dietmar showed in his answer how to use a cast to const to call the by-value argument overload. I didn't even think of that, but if you want to do that (it's limited to cutting off the by-reference version from consideration), do use a const_cast instead of a static_cast.

Or better, just make an rvalue expression out of the argument, e.g. by adding a handy little + sign in front,

    g( +a );

:-)

5 Comments

It's true that disabling overload resolution like this works, but it's hardly ideal. It'll never be possible to call the naked function on an lvalue like this...
kerrek, i'm unable to make sense of your comment. it think that means that it's meaningless. for example, it's hardly "ideal", well why make that comment to me instead of to the OP, who asks for this. or why not make it to yourself, since you added this solution when i showed you. jeez.
Not me, of course not -- I basically copied your answer to make mine complete ;-)
What's to be upset about? I made the comment so the OP can find out that while his question does have a direct answer, the resulting code will not be very nice.
Nice tip there, the unary minus :)
3

For the purpose of overload resolution, binding to a reference of the correct type is an exact match, exactly like binding to a non-reference of the correct type, so the two overloads have identical priority with respect to an lvalue int argument.

You could make the second overload take a int const &, in which case it can be used in the exact same way but will be a distinct overload.

Alternatively, you could avoid overload resolution altogether by casting the function type:

static_cast<void(&)(int)>(g)(a);
static_cast<void(&)(int&)>(g)(a);

You would have to do this for every invocation of the function where there is an ambiguity, though (i.e. when passing an lvalue int).

This video is mandatory viewing for you.

3 Comments

"the two overloads always have identical priority" does not follow from the preceding argument, because they do not always have the "correct type" wrt. to actual argument, in particular for const or rvalue argument. in particular, dietmar's answer shows one way to select the by-value function purely via the actual argument's type, and my answer shows another way to select the by-value argument, purely via the actual argument expression's rvalueness. i think my answer is much cuter, btw. it's certainly the shortest and most clear function invocation :-)
@Cheersandhth.-Alf: Ohh, of course, I see it now. The int overload can of course work in more general cases. I will rephrase that.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.