为什么编译器选择 bool 而不是 string 来进行 L"" 的隐式类型转换?

发布于 2024-07-09 12:47:45 字数 1077 浏览 13 评论 0 原文

最近引入了方法的重载,应用程序开始失败。 最终追踪到它,新方法正在我意想不到的地方被调用。

我们对其

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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

一个人练习一个人 2024-07-16 12:47:45

一、这个问题的原因:C++ Standard [over.ics .rank]/2.11 定义转换序列的顺序。 它说用户定义的转换序列比标准转换序列更糟糕。 在您的情况下,字符串文字会经历布尔转换(在 4.12 中定义。这是标准转换)。 它不使用用户定义的到 std::wstring 的转换,如果它采用其他重载,则需要该转换。

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


1)

比较隐式转换序列的基本形式(如[over.best.ics]中定义)

(2.1) 标准转换序列是比用户定义的转换序列或省略号转换序列更好的转换序列,并且
(2.2) 用户定义的转换序列是比省略号转换序列更好的转换序列。

First, the cause of this issue: C++ Standard [over.ics.rank]/2.11 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 at 4.12. This is a standard conversion). It does not use the user defined conversion to std::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)

When comparing the basic forms of implicit conversion sequences (as defined in [over.best.ics])

(2.1) a standard conversion sequence is a better conversion sequence than a user-defined conversion sequence or an ellipsis conversion sequence, and
(2.2) a user-defined conversion sequence is a better conversion sequence than an ellipsis conversion sequence.

旧情别恋 2024-07-16 12:47:45

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

为了解决这个问题,引入一个新的 setValue:

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

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:

void setValue(std::wstring const& name, const wchar_t * value);
你穿错了嫁妆 2024-07-16 12:47:45

由于 bool 是内置类型,因此首选从 wchar_t 到 bool 的转换。 我想说,最简单的解决方案是添加一个重载,该重载采用 wchar_t 数组并在其中显式转换:

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

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:

setValue( const std::wstring& name, const wchar_t s[] )
{
     setValue(name, wstring(s));
}
乖乖公主 2024-07-16 12:47:45

为了简化一点,以下代码

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

打印“bool version called”。 您确定您的代码仅因空字符串而失败吗?

To simplify a bit, the following code

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

prints "bool version called". Are you sure that your code fails only with the empty string?

我偏爱纯白色 2024-07-16 12:47:45

您可以使新函数采用 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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文