How to resolve ambiguity of call to overloaded function with literal 0 and pointer

纵饮孤独 提交于 2021-02-16 09:59:56

问题


I'm pretty sure this must have been here already, but I didn't find much information on how to solve this kind of problem (without casting on the call):

Given two overloads, I want that a call with function with a literal 0 always calls the unsigned int version:

void func( unsigned int ) {
    cout << "unsigned int" << endl;
}

void func( void * ) {
    cout << "void *" << endl;
}

func( 0 ); // error: ambiguous call

I understand why this happens, but I don't want to write func( 0u ) or even func( static_cast(0) ) all the time. So my questions are:

1) Is there a recommended way to do this in general?

2) Is there any problem with doing it the following way and what is the reason that this to works?

void func( unsigned int ) {
    cout << "unsigned int" << endl;
}

template <typename T>
void func( T * ) {
    static_assert( std::is_same<T, void>::value, "only void pointers allowed" );
    cout << "void *" << endl;
}

func( 0 ); // calls func( unsigned int )!

回答1:


1) Is there a recommended way to do this in general?

Yes, I would do it the way you did in 2). I don't think there is any deeper meaning as to why 2) works. The type int simply doesn't match T*, so it has no way to find out T. It will therefor ignore the template.




回答2:


What you're doing in 2) works and is probably the better way to do it.

In situations where you don't want to change the functions, you can do an explicit cast to give the compiler a hint:

func((void *) 0);
func((unsigned int) 0);



回答3:


I suggest you look at the null pointer from C++0x (see this). It defines a class representing null pointers of any type. The example you just gave was actually one motivating the inclusion of nullptr_t (the class) / nullptr (the value) to C++0x. It actually lets you disambiguate this call by putting 0 when wanting the unsigned int version, and nullptr when you want the other.

You may just implement this trick in a little utility class until your compiler supports it (or just use it if your compiler implements this part of the next standard).




回答4:


1) Is there a recommended way to do this in general?

The problem is simply that the literal 0 is an int, not an unsigned int, and there are valid conversions from int to unsigned int and from int to void*. I can't say that there's a recommended way to handle the problem. Aside from the ways you've already found, you could also add another overload:

void func(int i) 
{
    assert(i >= 0);
    return func(static_cast<unsigned int>(i));
}

2) Is there any problem with doing it the following way and what is the reason that this to works?

The template trick works because the rules for resolving calls to functions that are overloaded and have templated versions are designed to prefer non-templated versions of the overloaded functions.



来源:https://stackoverflow.com/questions/4610503/how-to-resolve-ambiguity-of-call-to-overloaded-function-with-literal-0-and-point

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!