8

I have two overload function with const std::string& and bool respectively. I am now calling the function with literal string. The bool version is called. This is a bit weird, and it is really a pitfall.

Can anyone explain why?

See the code below. The output is

Write == 1

#include <iostream>
#include <string>

void write(const std::string& name_) {
  std::cout << "Write == " << name_ << std::endl;
}

void write(bool name_) {
  std::cout << "Write == " << name_ << std::endl;
}

int main()
{
  write("data");
}
πάντα ῥεῖ
  • 1
  • 13
  • 116
  • 190
WeidongLian
  • 123
  • 4
  • 3
    There is a standard conversion sequence from `const char[5]` to `bool` (namely array-to-pointer conversion followed by boolean conversion), so that conversion is strictly better than the user-defined one. – Kerrek SB Jun 23 '15 at 00:14
  • 2
    Voted to reopen because this question is mainly about **overload resolution**. – Cheers and hth. - Alf Jun 23 '15 at 00:15
  • I think it is indirectly answered in the duplicate's accepted answer... – DigitalNinja Jun 23 '15 at 00:17
  • 2
    I don't feel an answer by me here right now would be accurate because I'm tired and with a headache, but in short, a built-in conversion such as pointer -> `bool` is better than a user-defined one such as pointer -> `std::string`. If necessary you can design around it by e.g. defining a function template that delegates to named type-specific functions. – Cheers and hth. - Alf Jun 23 '15 at 00:17
  • @Cheersandhth.-Alf I understand, but for me it is more natural to convert to const std::string&, especially it is a literal. Thanks for your answer. – WeidongLian Jun 23 '15 at 00:26
  • @WeidongLian Kerrek already explained why that will not happen. The conversion to `std::string` is a user-defined conversion, and it won't be selected over a standard conversion sequence. Add another overload - `void write(char const *name_)` to fix your problem. – Praetorian Jun 23 '15 at 00:33

1 Answers1

3

The issue is that your argument to write is not a value of type std::string (it is not a literal of std::string) but a character array.

Unfortunately, and I agree with you that it is a pitfall, the rules of the overload resolution will pick the conversion of array to boolean over conversion to const reference to string.

Mind you, there are in C++ 11 actual std::string literals, I won't go into the details here.

What fixes the overload is to convert explicitly to std::string:

write(std::string("data")) will do the right thing.

Prevent this issue in the future. It is indeed a pitfall.

TheCppZoo
  • 1,219
  • 7
  • 12
  • Another solution would be to add a `const char*` overload if raw string literals are meant to be passed to the function. – Emil Laine Jun 23 '15 at 10:44