为什么编译器为L“”的隐式类型转换选择bool over string?

问题描述:

最近引入了方法的重载,应用程序开始失败。 最后追踪它,新方法被称为我没有想到它会。为什么编译器为L“”的隐式类型转换选择bool over string?

我们有

setValue(const std::wstring& name, const std::wstring& value); 

std::wstring avalue(func()); 
setValue(L"string", avalue); 
std::wstring bvalue(func2() ? L"true", L"false"); 
setValue(L"bool", bvalue); 
setValue(L"empty", L""); 

它已更改,这样一个布尔值存储,当我们使用相同的字符串(字符串的内部数据存储)

setValue(const std::wstring& name, const std::wstring& value); 
setValue(const std::wstring& name, const bool& value); 

std::wstring avalue(func()); 
setValue(L"string", avalue); 
setValue(L"bool", func2()); 
setValue(L"empty", L""); << --- this FAILS!?! 

与L“的问题”是它隐式地投射,以前它很高兴成为一个std :: wstring,但不是它喜欢成为一个布尔。 MSVC编译器不抱怨,或提出警告,所以我担心,即使我“修复”setValue(L“空”,L“”);

setValue(L"empty", std::wstring()); 

别人可能晚点来,简单地使用setValue(L“empty”,L“”);并且必须再次追踪这个问题。

我们认为明确使用该方法,但它不是此用法的有效关键字。 有没有办法让编译器抱怨这个问题,或以其他方式防止这个问题?否则,我正在考虑改变采用bool的方法的名称,以确保它不能做出错误的猜测。

+0

添加到我的列表中,其中C++不是最好的语言。 – Qix 2016-10-14 08:34:38

首先,这个问题的原因:C++标准13.3.3.2定义了转换序列的顺序。它表示用户定义的转换序列比标准转换序列更差。你的情况发生的是字符串文字经历了一个布尔转换(定义在4.12这是一个标准转换)。它不使用用户定义的转换为std::wstring,如果其他过载需要转换。

我建议只更改其中一个重载的名称,或者直接添加接受字符串文字的重载(使用参数类型wchar_t const*)。

+0

感谢链接到标准和布尔的包装也是一个有用的提示。 – 2008-11-28 00:10:08

+0

当时我引用了错误的标准文本,并认为我的答案无疑是复杂的。我认为,为`wchar_t const *`添加一个oveload会更好。随意给Mark-Ransom打上复选标记,他们基本上都这么说。 – 2009-05-15 14:18:38

您可以使新函数采用除bool之外的其他类型 - 也许只是bool的代理 - 不能从文字字符串转换。但是,我真的只需重命名布尔函数并完成它。

为了简化一点,下面的代码

#include <iostream> 
using namespace std; 

void f(const string &s) 
{ cout << "string version called" << endl; } 

void f(const bool &b) 
{ cout << "bool version called" << endl; } 

int main() 
{ f("Hello World"); } 

打印 “布尔版本,称为”。你确定你的代码只能使用空字符串吗?

+0

我们目前不使用除空字符串以外的字符串文字。我相信你很正确,这与空白字符串无关。 – 2008-11-25 03:00:23

L“”是指向宽字符串的指针。编译器认为转换为bool优先于转换为std :: wstring。

要解决该问题,引入一个新的setValue:

void setValue(std::wstring const& name, const wchar_t * value); 

由于布尔是内置型,从为wchar_t到布尔转化是优选的。我会说最简单的解决方案是添加一个重载,它需要一个wchar_t数组并在其中明确投射:

setValue(const std::wstring& name, const wchar_t s[]) 
{ 
    setValue(name, wstring(s)); 
}