-1

I have code like this:

#include <cstdio>

void test(size_t const pos){
    printf("size_t\n");
}

void test(const void *ptr){
    printf("ptr\n");
}

//void test(int const pos){
//  printf("int\n");
//}

int main(){
    size_t x = 0;

    test(x);
    test(nullptr);
    test(&x);
//  test(0);
// some more that fail, but I do not care too much about them:
//  test(0U);
//  test(0L);
//  test(NULL);
}

When I un-comment test(0); it does not compile, because the compiler does not know how to convert '0'.

If I introduce 'int' overload, everything compiles again.

Is this correct way to avoid ambiguous function call?

UPDATE

Correct would mean - I want not to call pointer overload, except in case argument is pointer or nullptr is passed.

I am aware that current "setup" fails with 0U, 0L, NULL.

Nick
  • 9,962
  • 4
  • 42
  • 80
  • 1
    Possible duplicate of [How do I fix an "ambiguous" function call?](http://stackoverflow.com/questions/7549874/how-do-i-fix-an-ambiguous-function-call) – Jezor Sep 12 '16 at 12:53
  • 1
    Well... It depends on what result are you expecting. – Jezor Sep 12 '16 at 12:54
  • Well, since this resolved the compilation error, I don't know of any better definition of "correct". – Sam Varshavchik Sep 12 '16 at 12:54
  • Using a cast..? – Mansuro Sep 12 '16 at 12:56
  • 4
    "correct" really depends on what you want to do. 0 is an int **without** an implicit conversion so the `int` one will be taken if available. On the other cases both of them take 0 **after** an implicit conversion but none-has priority. So it's ambiguous. You can "choose" which implementation to take by using a cast (explicit conversion). – Hayt Sep 12 '16 at 12:58
  • 1
    @Jezor - is is not a duplicate – Nick Sep 12 '16 at 13:02
  • 2
    It is not a duplicate but it is Primarily Opinion Based. It really depends how you want to handle the input like Hayt stated. – NathanOliver Sep 12 '16 at 13:04
  • `test(0u);` actually fail to compile. `test(0l);` fails as well. infamous `test(NULL);` fails too. I need to do overload for each type. However I want to handle 0 only. – Nick Sep 12 '16 at 13:08
  • The above post describes no criteria to judge what is "correct", what is left is opinion. VTC as opinion based question without clarification. What is "correct" requires opinion, or information not presented. Attempts to ask for clarification in comments have failed to generate useful information. "Is not a duplicate" and "I want to handle 0" are not useful. – Yakk - Adam Nevraumont Sep 12 '16 at 13:09
  • What do you want to happen when `0`, `0U`, `0L` are entered? – NathanOliver Sep 12 '16 at 13:21
  • @Nick You can cast to a `void*` like, `test((void*)0)` – Arnav Borborah Sep 12 '16 at 13:21

1 Answers1

4

The literal 0 has type int. If there is a test(int) overload, then this will be called, because no conversion is required. Easy.

If there is no test(int) available, then the compiler will see whether the argument can be converted to either size_t or void* to satisfy the other overloads. A literal 0 can be implicitly converted to either type, and the conversion rules don't tell it to prefer either one, so the result is ambiguous.

In order to specify that you want test(size_t) called, you'll need to explicitly create a 0 of type size_t, i.e.

test(size_t{0});
Tristan Brindle
  • 16,281
  • 4
  • 39
  • 82