输出char8_t const *到cout和wcout,一个不编译

时间:2019-06-15 18:44:08

标签: c++ c++20

由于P1423R1为char8_t,char16_t和char32_t添加了删除的ostream插入器,因此,如果希望将这些类型流式传输到ostream,我们暂时需要编写自定义运算符。尝试为MSVC 2019 16.2.0 Preview 2.0执行此操作时。

#include <iostream>
#include <string>

using namespace std::literals;

template<typename Tostream>
Tostream&
operator<<( Tostream& os, std::u8string_view string ) {
  return os;
}

template<typename Tostream>
Tostream&
operator<<( Tostream& os, char8_t const* string ) {
  return os << std::u8string_view( string );
}

/// this must be commented out to compile
//std::ostream&
//operator<<( std::ostream& os, char8_t const* string ) {
//  return os << std::u8string_view( string );
//}


int
main() {
  std::cout << u8"utf-8"; 
  std::wcout << u8"utf-8";
}

我发现我的模板化尝试对于wcout成功,但不会为cout编译,除非我取消对operator<<的非模板化char8_t const *的注释。

error C2280:  'std::basic_ostream<char,std::char_traits<char>> &std::operator <<<std::char_traits<char>>(std::basic_ostream<char,std::char_traits<char>> &,const char8_t *)': attempting to reference a deleted function

问题是,在哪种情况下正确?不为cout编译是正确的还是为wcout编译是错误的?无论哪种方式,这似乎都是错误。

2 个答案:

答案 0 :(得分:1)

P1423尚未被C ++ 20接受(尽管它确实通过了Kona的LEWG审查),所以有趣的是Microsoft已经实现了它。

所显示的行为与P1423R1中指定的行为匹配。在最近的LWG审查中,要求删除char8_tchar16_tchar32_t相关的重载以用于宽泛的流。 P1423R2包含了这一更改,因此,如果实现(如果实现),示例代码的编译也将因std::wcout而失败。该修订版尚未在邮件中发布,但可以在https://rawgit.com/sg16-unicode/sg16/master/papers/p1423r2.html上进行预览。

正如@Nicol所提到的,对于删除的重载应具有的行为,我们尚未达成共识。他们应该隐式转码吗?如果是这样,如何处理转码错误?还是应该只是流字节?但是,如果附加了codecvt构面(将会期望执行编码),会发生什么情况。应该有std::u8out吗?还是我们应该提供更好的代码转换工具,并要求将其显式调用?第16研究组将致力于回答C ++ 23的这些问题。

答案 1 :(得分:0)

非模板函数始终在重载解析中的优先级高于模板函数。因此,std::operator<<(std::ostream&, const char8_t*)将赢得您的模板版本。

此外,删除这些功能的原因是不清楚它们应具有的行为(或更具体地说,委员会还没有准备好使Unicode成为现实)。如果您的目标只是将UTF-8编码的字符串的字节写入字节流,则应在您的终端上专门这样做,方法是将u8字符串显式转换为字节({{1} })指针,然后打印该指针:

char

不要试图强制标准库执行它明确不想执行的操作。特别是在这种情况下,C ++ 23可能会出现并提供这些功能的实现。