字符串文字匹配 bool 重载而不是 std::string

Posted

技术标签:

【中文标题】字符串文字匹配 bool 重载而不是 std::string【英文标题】:String literal matches bool overload instead of std::string 【发布时间】:2013-01-24 01:58:13 【问题描述】:

我正在尝试编写一个具有一些重载方法的 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++ 很陌生!

【问题讨论】:

@meh,因为它们不是实例函数。 你的 const char* 是一个原生类型提升到 bool 和一个构造值类型提升到 std::string会选择哪个。 ?现在猜猜编译器选择了哪一个.. 你传递的是 const char *,而不是字符串,试试 Output::Print(std::string("Hello World")) 关于“静态”:在 C++ 中,函数可以摆脱类系统的束缚,所以你不需要像在 Java 中那样制作准类。 @molbdnilo,是的,我知道你可以拥有无​​类函数,我猜有点像 javascript,其中函数不需要绑定到原型......再次,因为我是新手C++,我不确定这里的最佳做法是什么。 【参考方案1】:

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

【讨论】:

@LuchianGrigore 我同意这是更深层次的问题。我只是不确定 OP 是否知道他问过它=P 是的,我试过了,效果很好……只是看起来很不整洁!,我已将方法声明更改为 Print(const char* value),这似乎也有效……不知道是什么不过这里的最佳做法! 如果有人调用 Output::Print("Hello World") 被翻译成 Output::Print(bool value) 这不是任何人所期望的,如何强制错误或“正确”(预期的意思)翻译? 您知道在不同版本的C++之间执行标准转换的决定是否存在差异吗? IE。 C++17 和 C++98 会在完全相同的情况下执行从 const char * 到 bool 的标准转换吗?【参考方案2】:

不知道为什么没有人发布这个,但您可以添加另一个重载,为您从 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));
    
;

【讨论】:

我认为您的意思是 const char * value 用于超载。 固定,埃文。【参考方案3】:

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

【讨论】:

【参考方案4】:

从 C++14 开始,我们拥有来自 std::string_literals 命名空间的 operator""s,可用于告诉编译器绑定到 string(或 C++17 中的 string_view)重载:

using namespace std::string_literals;
Output::Print("Hello World"s);

打印:Hello World

【讨论】:

以上是关于字符串文字匹配 bool 重载而不是 std::string的主要内容,如果未能解决你的问题,请参考以下文章

C++ bool 表达式作为函数参数调用错误的重载

Visual C++ 2010 接受字符串作为重载函数中的 bool

匹配h2 / postgres中的文字百分比?

loadimage没有与参数列表匹配的重载函数 解决方案

loadimage没有与参数列表匹配的重载函数 解决方案

为啥 C 字符文字是整数而不是字符?