Строковый литерал соответствует перегрузке bool вместо std :: string

Я пытаюсь написать класс C ++, который имеет несколько перегруженных методов:

class Output
{
public:
static void Print(bool value)
{
std::cout << value ? "True" : "False";
}

static void Print(std::string value)
{
std::cout << value;
}
};

Теперь допустим, что я вызываю метод следующим образом:

Output::Print("Hello World");

это результат

Правда

Итак, почему, когда я определил, что метод может принимать логическое значение и строку, он использует логическую перегрузку, когда я передаю не логическое значение?

РЕДАКТИРОВАТЬ: я пришел из среды C # / Java, так что совершенно новый для C ++!

27

Решение

"Hello World" строковый литерал типа «массив из 12 const char«который может быть преобразован в» указатель на const char«который в свою очередь может быть преобразован в bool, Это именно то, что происходит. Компилятор предпочитает это использованию std::stringКонверсионный конструктор.

Последовательность преобразования, включающая конструктор преобразования, называется определяемая пользователем последовательность преобразования. Преобразование из "Hello World" к bool это стандартная последовательность преобразования. Стандарт гласит, что стандартная последовательность преобразования всегда лучше, чем определенная пользователем последовательность преобразования (§13.3.3.2 / 2):

стандартная последовательность преобразования (13.3.3.1.1) является лучшей последовательностью преобразования, чем определяемая пользователем последовательность преобразования или многоточечная последовательность преобразования

Этот анализ «лучшей последовательности преобразования» выполняется для каждого аргумента каждой жизнеспособной функции (и у вас есть только один аргумент), и лучшая функция выбирается разрешением перегрузки.

Если вы хотите убедиться, что std::string версия называется, нужно дать std::string:

Output::Print(std::string("Hello World"));
36

Другие решения

FWIW, он может быть адресован таким образом (если шаблоны могут быть использованы), если вы не хотите добавлять перегрузки для const char*,

#include <iostream>
#include <string>
#include <type_traits>

template <typename Bool,
typename T = std::enable_if_t<std::is_same<Bool, bool>{}>>
void foo(Bool)
{
std::cerr << "bool\n";
}

void foo(const std::string&)
{
std::cerr << "string\n";
}

int main()
{
foo("bar");
foo(false);
}
3

Не знаю, почему никто не опубликовал это, но вы можете добавить еще одну перегрузку, которая преобразует из const char * в std :: string для вас. Это избавляет абонента от необходимости беспокоиться об этом.

class Output
{
public:
static void Print(bool value)
{
std::cout << value ? "True" : "False";
}

static void Print(std::string value)
{
std::cout << value;
}

// Just add the override that cast to std::string
static void Print(const* char value)
{
Output::Print(std::string(value));
}
};
0
По вопросам рекламы [email protected]