In Visual C++ 2017 (with /std:c++14 or with /std:c++17), the following code works:
void TakePtr(char*); // const or not
int main()
{
TakePtr(char{});
TakePtr(char());
}
I don't understand why it works.
Apparently, the following would also work (as expected):
void TakeChar(char);
TakeChar(char{});
TakeChar(char());
How does the compiler deduce (or convert) the type char to char*, when char{} or char() is used as an argument?
Now, if I have both char and char* overloads, it works without any error/warning about ambiguity:
void TakePtr(char*);
void TakePtr(char);
TakePtr(char{}); // Chooses 'char'
TakePtr(char()); // Chooses 'char'
Why is the compiler okay with char{} for TakePtr(char*)?
And why doesn't it give a warning/error when choosing the better version? Such behavior is bound to break existing code.
For sure, the compiler isn't happy with:
void TakePtr(char*);
char c{};
TakePtr(c);
Because Visual lies a lot. Especially older one. Your code prompts clang to report an error:
<source>:9:6: error: no matching function for call to 'TakePtr'
TakePtr(char{});
^~~~~~~
<source>:5:6: note: candidate function not viable: no known conversion from 'char' to 'char *' for 1st argument
void TakePtr(char*); // const or not
^
<source>:10:6: error: no matching function for call to 'TakePtr'
TakePtr(char());
^~~~~~~
<source>:5:6: note: candidate function not viable: no known conversion from 'char' to 'char *' for 1st argument
void TakePtr(char*); // const or not
^
2 errors generated.
Visual is known to be "wonky" in term of following C++ standard, so don't rely on it too much. Try to verify with clang / gcc, just to be sure.
This is simply MSVC being behind: the rule in C++03 was that any constant expression of integer type and value 0 was a null pointer constant and could thus be converted to char*. Certainly char() qualifies—and char{} means the same thing, although it never overlapped with the rule.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With