26

I was trying to clean up some code that uses char* with std::string and ran into a problem that is illustrated by the following code.

void Foo( int xIn , const std::string & fooIn )
{
    std::cout << "string argument version called \n";
}

void Foo( int xIn ,  bool flagIn = true )
{
    std::cout << "bool argument version called \n";
}

int main()
{
    int x = 1;
    Foo( x , "testing" );
    return 0;
}

When I run the program I get bool argument version called. Is a char* to bool conversion preferred over char* to const std::string& or is Visual Studio 2008 playing tricks on me ?

John Dibling
  • 99,718
  • 31
  • 186
  • 324
parapura rajkumar
  • 24,045
  • 1
  • 55
  • 85

3 Answers3

27

Surprising as this behaviour is, the compiler is compliant: char* to bool conversion is preferred over the conversion to std::string.

Read more here.

The exact rules are spelled out in the C++ standard. They're surprisingly complicated, but the following paragraph is crucial here:

C++11 13.3.3.2 Ranking implicit conversion sequences [over.ics.rank]

2 When comparing the basic forms of implicit conversion sequences (as defined in 13.3.3.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

char*-to-bool requires a "standard conversion sequence" whereas char*-to-string requires a "user-defined conversion sequence". Therefore, the former is preferred.

NPE
  • 486,780
  • 108
  • 951
  • 1,012
  • 4
    @Vlad.. what is the **safe bool** alternative ? – parapura rajkumar Dec 02 '11 at 16:30
  • @vlad: The misbehaving type is built-in. What do you mean? – UncleBens Dec 02 '11 at 16:36
  • 2
    @Vlad: The [safe bool idiom](http://en.wikibooks.org/wiki/More_C%2B%2B_Idioms/Safe_bool) is useful when you want your user-defined type to provide a conversion to bool. Here, the conversion is between two primitive types, so the safe bool idiom is not applicable. – Luc Touraille Dec 02 '11 at 16:38
  • @UncleBens I mean this - http://www.artima.com/cppsource/safebool.html So instead of using built-in bool, you can use this wrapper to avoid the char * vs bool problem in ADL. –  Dec 02 '11 at 16:39
  • 1
    @LucTouraille: You are right. I meant replacing `bool` with some sort of `Safebool` in the method when users really mean bool... One could also use enable_if to prevent `const char *` from being passed. Just thoughts. –  Dec 02 '11 at 16:41
  • That's quite different than the "safe bool idiom" – Mooing Duck Dec 02 '11 at 17:50
9

They are both a potential match, but the bool version is preferred by the compiler because in order to match the string version a user-provided (or, in this case, library-provided) conversion function is required.

If you really want to do this, providing an overload for const char* can get you there:

void Foo( int xIn, const char* in)
{
    return Foo( xIn, string(in) );
}

I would guess that by doing this, there's a very good chance that the compiler will perform quite a bit of optimization on it.

John Dibling
  • 99,718
  • 31
  • 186
  • 324
1

One simple fix would be to change the bool to int - there is an implicit conversion from a pointer to bool, but not to int. bool to int is not a problem, so the existing code that passes bools will continue to work.

Unfortunately this does impact the code readability a little by masking the parameter's intent.

Mark Ransom
  • 299,747
  • 42
  • 398
  • 622