文字列リテラルは、std::string の代わりにブール オーバーロードに一致します

"Hello World" 「12 const char の配列」型の文字列リテラルです。 " これは "const char へのポインタ" に変換できます " これは bool に変換できます .それがまさに起こっていることです。コンパイラは std::string を使用するよりもこれを優先します の変換コンストラクター。

変換コンストラクターを含む変換シーケンスは、ユーザー定義の変換シーケンスと呼ばれます。 . "Hello World" からの変換 bool標準の変換シーケンスです .標準では、標準の変換シーケンスは常にユーザー定義の変換シーケンスよりも優れていると述べています (§13.3.3.2/2):

この「より良い変換シーケンス」分析は、実行可能な各関数の各引数に対して行われ (引数は 1 つしかありません)、オーバーロード解決によってより良い関数が選択されます。

std::string を確認したい場合 バージョンが呼び出されたら、std::string を指定する必要があります :

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

誰もこれを投稿しなかった理由はわかりませんが、 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));
    }
};

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);
}