GCC 问题与 static_cast<std::u16string>

GCC problem with static_cast<std::u16string>

本文关键字:std 问题 u16string gt lt cast GCC static      更新时间:2023-10-16

摘要

我有一个类,我在其中添加了一个要转换为std::u16string的类型转换运算符。此运算符的签名如下所示:

operator const std::u16string() const;

在我的.cpp文件中,我尝试将类类型的对象转换为std::u16string如下所示:

std::u16string sUTF16Password = static_cast<std::u16string>(Password_);

在Visual Studio 2017上,这工作得很好。但是,我的树莓派上的GCC 6.3在编译时给出了以下错误:

error :  call of overloaded 'basic_string(MyClass&)' is ambiguous

编写此类型转换的正确方法是什么?在谷歌上搜索为字符编码转换带来了很多点击,但这不是我的问题。我不明白为什么尽管使用了static_cast,但在这里调用了basic_string构造函数。

完整示例

下面是一个最小示例。用g++ main.cpp编译它在我的树莓派上失败了。

#include <iostream>
#include <string>
class MyClass
{
private:
std::u16string Str;
public:
MyClass() { Str = u"abcd"; }
operator const char16_t*() const { return Str.c_str(); }
operator std::u16string() const { return Str; }
};
int main()
{
MyClass Tester;
std::u16string TestStr = static_cast<std::u16string>(Tester);
for (size_t idx = 0; idx < TestStr.size(); idx++)
std::cout << idx << ": " << TestStr[idx] << std::endl;
return 0;
}

gcc --version的输出是gcc (Raspbian 6.3.0-18+rpi1+deb9u1) 6.3.0 20170516

g++ main.cpp的完整输出为:

main.cpp: In function ‘int main()’:
main.cpp:17:61: error: call of overloaded ‘basic_string(MyClass&)’ is ambiguous
std::u16string TestStr = static_cast<std::u16string>(Tester);
^
In file included from /usr/include/c++/6/string:52:0,
from /usr/include/c++/6/bits/locale_classes.h:40,
from /usr/include/c++/6/bits/ios_base.h:41,
from /usr/include/c++/6/ios:42,
from /usr/include/c++/6/ostream:38,
from /usr/include/c++/6/iostream:39,
from main.cpp:1:
/usr/include/c++/6/bits/basic_string.h:476:7: note: candidate: std::__cxx11::basic_string<_CharT, _Traits, _Alloc>::basic_string(std::__cxx11::basic_string<_
CharT, _Traits, _Alloc>&&) [with _CharT = char16_t; _Traits = std::char_traits<char16_t>; _Alloc = std::allocator<char16_t>]
basic_string(basic_string&& __str) noexcept
^~~~~~~~~~~~
/usr/include/c++/6/bits/basic_string.h:454:7: note: candidate: std::__cxx11::basic_string<_CharT, _Traits, _Alloc>::basic_string(const _CharT*, const _Alloc&
) [with _CharT = char16_t; _Traits = std::char_traits<char16_t>; _Alloc = std::allocator<char16_t>]
basic_string(const _CharT* __s, const _Alloc& __a = _Alloc())
^~~~~~~~~~~~
/usr/include/c++/6/bits/basic_string.h:397:7: note: candidate: std::__cxx11::basic_string<_CharT, _Traits, _Alloc>::basic_string(const std::__cxx11::basic_st
ring<_CharT, _Traits, _Alloc>&) [with _CharT = char16_t; _Traits = std::char_traits<char16_t>; _Alloc = std::allocator<char16_t>]
basic_string(const basic_string& __str)
^~~~~~~~~~~~

如果我删除类型转换以const char16_t*此示例可以很好地编译。我仍然不明白为什么同时拥有两个类型转换是一个问题。

如果编译为 C++14(或更早版本(,则会收到此不明确的调用,因为std::u16string(char16_t*)参与重载解析(通过MyClass::operator const char16_t*()(以及似乎更好的匹配MyClass::operator std::u16string()

这可以通过几种方式克服:

使用 GCC
  • 7 或更高版本编译为 C++17(或更高版本((遗憾的是,这对 GCC 6 没有帮助(。
  • 删除operator const char16_t*()
  • explicit添加到operator const char16_t*()(或同时添加到两个转换运算符(。