выводя char8_t const * в cout и wcout, один компилирует не - PullRequest
0 голосов
/ 15 июня 2019

Поскольку P1423R1 добавляет удаленные вставки ostream для char8_t, char16_t и char32_t, мы на мгновение остаемся в ситуации, когда нам нужно написать пользовательские операторы, если мы хотим передать эти типы в ostreams.При попытке сделать это для 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 ]

1 голос
/ 21 июня 2019

P1423 еще не был принят для C ++ 20 (хотя он и прошел проверку LEWG в Kona), поэтому интересно, что Microsoft уже реализовала (частично) его.

Показанное поведениесоответствует тому, что указано в P1423R1.Во время недавнего обзора LWG было предложено удалить перегрузки, связанные с char8_t, char16_t и char32_t, для широких потоков.P1423R2 включает это изменение, поэтому компиляция примера кода также не будет выполнена для std::wcout, когда / если это будет реализовано.Эта ревизия еще не была опубликована в почтовом сообщении, но ее можно предварительно просмотреть в https://rawgit.com/sg16-unicode/sg16/master/papers/p1423r2.html.

Как уже упоминалось @Nicol, у нас пока нет единого мнения о том, каким должно быть поведение удаленных перегрузок.Должны ли они неявно транскодировать?Если да, то как обрабатываются ошибки в транскодировании?Или они должны просто передавать байты?Но что происходит, если присоединен фасет codecvt (ожидается кодирование выполнения).Должен ли быть std::u8out?Или мы должны предоставить лучшие средства транскодирования и требовать их явного вызова?ИК16 будет работать, чтобы ответить на эти вопросы для C ++ 23.

0 голосов
/ 15 июня 2019

Не шаблонные функции всегда имеют приоритет в разрешении перегрузки над шаблонными функциями.Следовательно, std::operator<<(std::ostream&, const char8_t*) победит ваши версии шаблона.

Кроме того, причина, по которой эти функции были удалены, заключается в том, что неясно, какое поведение они должны иметь (или, более конкретно, комитет не готов сделать Unicode).реальная вещь).Если ваша цель состоит в том, чтобы просто записать байты строки в кодировке UTF-8 в поток байтов, то вы должны сделать это специально на своем конце, явно преобразовав строку u8 в указатель байта (char),и затем напечатайте это:

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

Не пытайтесь заставить стандартную библиотеку делать то, что она явно не хочет делать.Особенно в этом случае, когда C ++ 23 может прийти и обеспечить реализацию этих функций.

...