Почему цитированная строка соответствует сигнатуре метода bool до std::string?

Для использования следующих методов:

// Method 1
void add(const std::string& header, bool replace);

//Method 2
void add(const std::string& name, const std::string& value);

Похоже, что следующий код в конечном итоге вызовет метод 1 вместо метода 2:

something.add("Hello", "World");

Я закончил создание другого метода, который выглядит так:

//Method 3
void MyClass::add(const char* name, const char* value) {
    add(std::string(name), std::string(value));
}

Это сработало. Таким образом, казалось бы, когда метод принимает "цитированную строку", он будет соответствовать в следующем порядке:

  • const char*
  • bool
  • std::string

Почему цитированная строка должна рассматриваться как bool до std::string? Это обычное поведение? Я написал достойный код для этого проекта и не имел никаких других проблем с выбранной сигнатурой метода...

Ответы

Ответ 1

Мое предположение заключается в том, что преобразование из указателя в bool является неявным преобразованием примитивного типа, где преобразование в std::string требует вызова конструктора и создания временного.

Ответ 2

В вашем случае у вас есть перегруженные функции. Разрешение перегрузки происходит в соответствии с разделом 13.3.

С++ 03 13.3.3.2/2:

При сравнении основных форм неявных последовательностей преобразования (как определено в 13.3.3.1)
- стандартная последовательность преобразования (13.3.3.1.1) является лучшей последовательностью преобразования, чем пользовательская последовательность преобразования или последовательность преобразования многоточия, и
- пользовательская последовательность преобразования (13.3.3.1.2) является лучшей последовательностью преобразования, чем последовательность преобразования многоточия (13.3.3.1.3).

Указатель преобразования в bool является стандартным преобразованием. Указатель преобразования в std::string - это определяемое пользователем преобразование.

4.12 Логические преобразованияЗначение r арифметики, перечисления, указателя или указателя на тип члена можно преобразовать в rvalue типа bool. Значение нуля, значение нулевого указателя или значение указателя нулевого элемента преобразуется в значение false; любое другое значение преобразуется в значение true.

Ответ 3

Указатели имеют неявное преобразование в bool. Возможно, вы видели следующее:

void myFunc(int* a)
{
    if (a)
        ++(*a);
}

Теперь, в С++, неявные преобразования между встроенными типами имеют приоритет над преобразованиями между типами классов. Например, если у вас есть класс:

class Int
{
public:
    Int(int i) {}
}

И вы перегрузили функцию для long и Int:

void test(long n) {cout << "long";}
void test(Int n) {cout << "Int";}

Вы увидите, что следующий код вызывает длительную перегрузку:

int i;
test(i);