3

Why would the code give an output: bool ? Is there any way I could make the const char* to match the string version?

#include <string>
#include <iostream>

void func(bool)
{
    std::cout << "bool" << std::endl;
}

void func(const std::string&)
{
    std::cout << "string" << std::endl;
}

int main(int argc, char* argv[])
{
    func("hello");
}
jayatubi
  • 1,972
  • 1
  • 21
  • 51

3 Answers3

11

This happens because the compiler will prefer built-in conversions to user-defined conversions. The conversion from a pointer to a bool is built-in, so that overload is selected rather than constructing a std::string.

You could add an overload which takes a const char* and forwards it to the std::string version:

void func(const char* arg)
{
    func(std::string{arg});
}
TartanLlama
  • 63,752
  • 13
  • 157
  • 193
  • Can you explain the operator `{}`? – jayatubi Jun 23 '15 at 08:23
  • That's [uniform initialization](http://programmers.stackexchange.com/questions/133688/is-c11-uniform-initialization-a-replacement-for-the-old-style-syntax). It's a C++11 feature. – TartanLlama Jun 23 '15 at 08:25
6

To answer the why:

Function matching is the process by which the compiler selects which function to call among an overload set. Here, there are two viable candidates (the two functions you defined). To pick one, the compiler ranks the conversion they imply.

The first candidate void func(bool) implies an array-to-pointer conversion followed by a boolean conversion (from const char[6] to const char* to bool) The second candidate implies a user-defined conversion (calling the std::string ctor taking a const char*)

The second conversion has lower ranking, so the first candidate is selected as the best match.

Angew is no longer proud of SO
  • 167,307
  • 17
  • 350
  • 455
Ad N
  • 7,930
  • 6
  • 36
  • 80
2

According to the standard N4431 §13.3.3.2/2 Ranking implicit conversion sequences [over.ics.rank] (emphasis mine):

When comparing the basic forms of implicit conversion sequences (as defined in 13.3.3.1) (2.1) — a standard conversion sequence (13.3.3.1.1) is a better conversion sequence than a user-defined conversion sequence or an ellipsis conversion sequence, and (2.2) — a user-defined conversion sequence (13.3.3.1.2) is a better conversion sequence than an ellipsis conversion sequence (13.3.3.1.3).

Consequently, because the char const * to bool is a standard implicit conversion compared to the implicit conversion to std::string which is a user-defined conversion is a better conversion and is preferred in overload resolution.

In order to force overload resolution to choose the std::string version:

func(std::string("hello"));
101010
  • 41,839
  • 11
  • 94
  • 168
  • 1
    This looks like the only straight-up answer that explains how the language works without putting any blame on "the compiler". – Kerrek SB Jun 23 '15 at 08:48
  • @KerrekSB Isn't the language actually defined by what a conforming compiler does? – Angew is no longer proud of SO Jun 23 '15 at 09:39
  • @Angew: That's an extremely perverted way of viewing the world, but I guess you could see it that way... – Kerrek SB Jun 23 '15 at 09:41
  • @KerrekSB I don't actually view the world that way (1.1/1 and 1.4/2 notwithstanding). It's just that I don't see that much of a distinction between saying "the language dictates this" and "the compiler does this." As long as the compiler is following the standard, I consider these two equivalent. – Angew is no longer proud of SO Jun 23 '15 at 09:47
  • @Angew: Code makes sense even if you never compile it. You can talk about the expression `f(x)` without compiling code, and overload resolution is still relevant. Code and logic are more fundamental than the act of compilation. It seems like pointless noise and distraction to pollute a discussion of code with ancillary musings about compilation. Why not also discuss what the code would look like when printed in pink Comic Sans? – Kerrek SB Jun 23 '15 at 09:50