8
votes

There is global function (just example):

void func( int i )
{
    std::cout << i + 100 << std::endl;
}

I assume that calling this function with char argument does not make any sense so I use delete:

void func(char) = delete;

So I expect that following calls should be possible:

func(1);
func(3.1);
func(true);

And call with char argument should be forbiden:

func('a');

But that is not true. When calling func('a') I get as expected:

error: use of deleted function ‘void func(char)’

But during calling func(2.3) I get:

error: call of overloaded ‘func(double)’ is ambiguous

Why do I get this error? Without deleting function with char arguments double was converted to int and func(int) was called, why now it is forbidden?

3
"Why do I get this error?" You are aware that char can be automatically converted to an int and to a double in turn? - user0042
Everything you have after EDITED seems like an answer to your question. If that's your answer, please remove it from the question and post it as an answer. If, as it seems, you're just echoing an existing one, don't post a duplicate answer; just delete it from your question. - Nic

3 Answers

12
votes

When you call

func(2.3)

you pass a double to the function. The list of candidates contains both func(int) and func(char), as overload resolution happens before delete kicks in:

If the function is overloaded, overload resolution takes place first, and the program is only ill-formed if the deleted function was selected Ref: cppreference.com, see Avishai's answer for precise standard quotes.

Now double can be converted both to char and int, hence the ambiguity.

Without deleting function with char arguments double was converted to int and func(int) was called, why now it is forbidden?

You get an ambiguity error even without deleteing the char version, see live here. Of course if you only define the func(int), then there will be no ambiguity so double will happily be converted to an int.

1
votes

Any time a non-exact match is passed in for a function parameter, a conversion must be done. When you have two functions, regardless if one is deleted, they still participate in overload resolution. The compiler picks the best match, then either generates a call to it, or fails if the function is inaccessible or deleted.

For overload resolution to work, it makes a set of candidate functions then sees which has the shortest conversion path to the set of parameters. As far as the rules go, all builtin numeric types are an "equal" conversion. Therefore, if you call with 2.5, which is a double, it must convert and can convert equally to a char OR to an int, with the same ranking, so the call is ambiguous.

0
votes

It is still ambiguous, as the compiler tries to resolve the overload before checking for deleted functions. See:

§8.4.3 Deleted definitions

A program that refers to a deleted function implicitly or explicitly, other than to declare it, is ill-formed. [ Note: This includes calling the function implicitly or explicitly and forming a pointer or pointer-to-member to the function. It applies even for references in expressions that are not potentially-evaluated. If a function is overloaded, it is referenced only if the function is selected by overload resolution. — end note ]

§13.3.3.1 Implicit conversion sequences:

Implicit conversion sequences are concerned only with the type, cv-qualification, and value category of the argument and how these are converted to match the corresponding properties of the parameter. Other properties, such as the lifetime, storage class, alignment, accessibility of the argument, whether the argument is a bit-field, and whether a function is deleted (8.4.3), are ignored. So, although an implicit conversion sequence can be defined for a given argument-parameter pair, the conversion from the argument to the parameter might still be ill-formed in the final analysis.