C++:避免在重载中将字符串自动转换为布尔值
C++: avoid automatic conversion of string to bool in overloads
我想创建一组方法,这些方法将根据其类型输出具有特殊格式的值。当我这样做时,到目前为止看起来非常好:
static void printValue(std::ostringstream& out, int value) {
out << value;
}
static void printValue(std::ostringstream& out, double value) {
out << value;
}
static void printValue(std::ostringstream& out, const std::string& value) {
out << "\"" << escapeString(value) << "\"";
}
测试:
printValue(std::cout, 123); // => 123
printValue(std::cout, 3.14); // => 3.14
printValue(std::cout, "foo"); // => "foo"
但是,一旦我添加 bool
重载:
static void printValue(std::ostringstream& out, bool value) {
out << (value ? "true" : "false");
}
...事情坏了,因为添加字符串调用似乎默认使用基于 bool
的重载:
printValue(std::cout, 123); // => 123
printValue(std::cout, 3.14); // => 3.14
printValue(std::cout, true); // => true
printValue(std::cout, "foo"); // => true <= !!!
有什么方法可以避免这种自动转换为布尔值并强制编译器为字符串选择正确的方法吗?
您可以添加一个模板重载,它引用大小为 N
的 char
数组,其中 N
是一个模板参数,and/or 接受一个const char*
.
template <std::size_t N>
static void printValue(sts::ostringstream& out, const char (&str)[N])
{
out << str;
}
为什么会这样:
当编译器尝试选择 "best" 函数来调用给定的一些参数时,它大致按以下方式对重载集进行优先级排序:
- 精确匹配:例如,如果您传递一个
const char*
而该函数接受一个 const char*
,那就太好了
- 标准转换序列:例如,将
const char[4]
转换为 const char*
,然后将 const char*
转换为 bool
(基于对 nullptr
).或者将 short
提升为 int
- 这些转化也有自己的优先顺序,为了简洁起见我们可以忽略它们
- 用户定义的转换:基本上,转换为一些非fundamental type(通过构造函数或转换运算符)
因为您提供的是字符文字 "foo"
它具有从 const char[4]
到 const char*
的标准转换序列(通过数组到指针的转换,请参阅 [conv.array] ),然后通过布尔转换从 const char*
到 bool
(参见 [conv.bool])。
因此,虽然可以通过用户定义的转换用 "foo"
构造 const std::string&
,但这种转换的优先级低于标准转换序列,因此选择了布尔值.
你能做什么:
- 预料到这一点并为
const char*
或 const char[N]
写一个重载,例如
- 调用函数时创建一个
std::string
:printValue(std::string{"foo"});
我想创建一组方法,这些方法将根据其类型输出具有特殊格式的值。当我这样做时,到目前为止看起来非常好:
static void printValue(std::ostringstream& out, int value) {
out << value;
}
static void printValue(std::ostringstream& out, double value) {
out << value;
}
static void printValue(std::ostringstream& out, const std::string& value) {
out << "\"" << escapeString(value) << "\"";
}
测试:
printValue(std::cout, 123); // => 123
printValue(std::cout, 3.14); // => 3.14
printValue(std::cout, "foo"); // => "foo"
但是,一旦我添加 bool
重载:
static void printValue(std::ostringstream& out, bool value) {
out << (value ? "true" : "false");
}
...事情坏了,因为添加字符串调用似乎默认使用基于 bool
的重载:
printValue(std::cout, 123); // => 123
printValue(std::cout, 3.14); // => 3.14
printValue(std::cout, true); // => true
printValue(std::cout, "foo"); // => true <= !!!
有什么方法可以避免这种自动转换为布尔值并强制编译器为字符串选择正确的方法吗?
您可以添加一个模板重载,它引用大小为 N
的 char
数组,其中 N
是一个模板参数,and/or 接受一个const char*
.
template <std::size_t N>
static void printValue(sts::ostringstream& out, const char (&str)[N])
{
out << str;
}
为什么会这样:
当编译器尝试选择 "best" 函数来调用给定的一些参数时,它大致按以下方式对重载集进行优先级排序:
- 精确匹配:例如,如果您传递一个
const char*
而该函数接受一个const char*
,那就太好了 - 标准转换序列:例如,将
const char[4]
转换为const char*
,然后将const char*
转换为bool
(基于对nullptr
).或者将short
提升为int
- 这些转化也有自己的优先顺序,为了简洁起见我们可以忽略它们
- 用户定义的转换:基本上,转换为一些非fundamental type(通过构造函数或转换运算符)
因为您提供的是字符文字 "foo"
它具有从 const char[4]
到 const char*
的标准转换序列(通过数组到指针的转换,请参阅 [conv.array] ),然后通过布尔转换从 const char*
到 bool
(参见 [conv.bool])。
因此,虽然可以通过用户定义的转换用 "foo"
构造 const std::string&
,但这种转换的优先级低于标准转换序列,因此选择了布尔值.
你能做什么:
- 预料到这一点并为
const char*
或const char[N]
写一个重载,例如 - 调用函数时创建一个
std::string
:printValue(std::string{"foo"});