【问题标题】:outputting char8_t const* to cout and wcout, one compiles one not将 char8_t const* 输出到 cout 和 wcout,一个编译一个不编译
【发布时间】:2019-06-15 18:44:08
【问题描述】:

由于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 编译,除非我取消对char8_t const * 的非模板化operator&lt;&lt; 的注释。

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 编译是错误的?无论哪种方式,这似乎都是错误。

【问题讨论】:

  • 您在寻找language-lawyer吗?
  • @RobertAndrzejuk 不确定。你觉得我需要一个吗?

标签: c++ c++20


【解决方案1】:

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

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

正如@Nicol 提到的,我们还没有就删除的重载的行为达成共识。他们应该隐式转码吗?如果是这样,如何处理转码错误?或者他们应该只是流式传输字节?但是,如果附加了codecvt 方面会发生什么(它将期望执行编码)。应该有std::u8out 吗?还是我们应该提供更好的转码工具并要求它们被显式调用? SG16 将致力于为 C++23 回答这些问题。

【讨论】:

    【解决方案2】:

    非模板函数总是在重载决议中优先于模板函数。因此,std::operator&lt;&lt;(std::ostream&amp;, const char8_t*) 将赢得您的模板版本。

    此外,这些函数被删除的原因是不清楚它们应该有什么行为(或者更具体地说,委员会还没有准备好让 Unicode 成为现实)。如果您的目标只是将 UTF-8 编码字符串的字节写入字节流,那么您应该通过将 u8 字符串显式转换为字节 (char) 指针来专门执行此操作,然后打印出来:

    std::cout << reinterpret_cast<const char*>(u8"utf-8");
    

    不要试图强迫标准库做它明确不想做的事情。尤其是在这种情况下,当 C++23 可能出现并提供这些功能的实现时。

    【讨论】:

    • 是的,我理解非模板版本获胜,但是模板版本呢,为什么在一种情况下它就足够了,而在另一种情况下就不行了?
    • 我的目标是使用 codecvt::out 进行转换,因为 Windows 控制台通常需要 latin-1 并且转换是不够的。
    • @Thomas:谁知道呢?也许他们没有=删除另一个?也许他们的wchar_t 版本是模板化的。关键是你正在做的事情不应该工作。
    • 好的,但是应该怎么做呢?我是否需要为所有 unicode 字符类型char8_t、..、char32_t 和所有字符串视图类型编写非模板版本?
    • 是的,显然只有 basic_ostream&lt;char, _Traits&gt; 版本被删除 char8_tconst char8_t*
    猜你喜欢
    • 2022-09-27
    • 2019-09-18
    • 1970-01-01
    • 1970-01-01
    • 2014-07-03
    • 1970-01-01
    • 2011-09-07
    • 2012-02-15
    相关资源
    最近更新 更多