最近引入了方法的重载,应用程序开始失败。
最终追踪到它,新方法正在我意想不到的地方被调用。
我们对其
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"" );
进行了更改,以便在存储 bool 值时我们使用相同的字符串(字符串的内部数据存储)
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"empty", L"" ); 成为
setValue( L"empty", std::wstring() );
其他人可能会稍后出现,只需使用 setValue( L"empty", L"" ); 并且必须再次追踪这个问题。
我们考虑在方法上使用显式,但它不是这种用法的有效关键字。
有没有办法让编译器抱怨这个问题,或者以其他方式阻止这个问题? 否则,我正在考虑更改采用 bool 的方法的名称,以确保它不会做出错误的猜测。
Having recently introduced an overload of a method the application started to fail.
Finally tracking it down, the new method is being called where I did not expect it to be.
We had
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"" );
It was changed so that when a bool value is stored we use the same strings (internal data storage of strings)
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!?!
The problem with L"" is that it is implicitly casting and previously it was happy to be a std::wstring, but not it prefers to be a bool.
The MSVC compiler does not complain, or raise warning, so I'm worried that even if I "fix" the setValue( L"empty", L"" ); to be
setValue( L"empty", std::wstring() );
somebody else may come later and simply use setValue( L"empty", L"" ); and have to track down this issue again.
We thought to use explicit on the method but it is not a valid keyword for this usage.
Is there some way to get the compiler to complain about this, or otherwise prevent the issue? Otherwise I'm thinking to change the name of the method which takes a bool to ensure it can't make an incorrect guess.
发布评论
评论(5)
一、这个问题的原因:C++ Standard
[over.ics .rank]/2.1
1 定义转换序列的顺序。 它说用户定义的转换序列比标准转换序列更糟糕。 在您的情况下,字符串文字会经历布尔转换(在4.12
中定义。这是标准转换)。 它不使用用户定义的到std::wstring
的转换,如果它采用其他重载,则需要该转换。我建议简单地更改其中一个重载的名称,或者添加一个直接接受字符串文字的重载(使用参数类型
wchar_t const*
)。1)
First, the cause of this issue: C++ Standard
[over.ics.rank]/2.1
1 defines an order for conversion sequences. It says that a user defined conversion sequence is worse than a standard conversion sequence. What happens in your case is that the string literal undergoes a boolean-conversion (defined at4.12
. This is a standard conversion). It does not use the user defined conversion tostd::wstring
which would be needed if it took the other overload.I would recommend to simply change the name of one of the overloads or adding an overload that accepts the string literal directly (using parameter type
wchar_t const*
).1)
L"" 是指向宽字符串的指针。 编译器认为转换为 bool 优先于转换为 std::wstring。
为了解决这个问题,引入一个新的 setValue:
L"" is a pointer to a wide character string. The compiler believes that the conversion to a bool takes precedence over a conversion to a std::wstring.
To fix the problem, introduce a new setValue:
由于 bool 是内置类型,因此首选从 wchar_t 到 bool 的转换。 我想说,最简单的解决方案是添加一个重载,该重载采用 wchar_t 数组并在其中显式转换:
Since bool is a built-in type, the conversion from wchar_t to bool is preferred. I would say that the simplest solution is to add an overload that takes a wchar_t array and cast explicitly in there:
为了简化一点,以下代码
打印“bool version called”。 您确定您的代码仅因空字符串而失败吗?
To simplify a bit, the following code
prints "bool version called". Are you sure that your code fails only with the empty string?
您可以使新函数采用 bool 以外的其他类型——可能只是 bool 的代理——它不能从文字字符串转换。 但实际上我只是重命名布尔函数并完成它。
You could make the new function take some other type than bool--maybe just a proxy for bool--which is not convertible from a literal string. But really I'd just rename the bool-taking function and be done with it.