[libc++] Overhaul std::quoted; fix its relationship to character traits.
Move `__quoted_output_proxy` into the one file that uses it. A `const char*` has no associated traits class, so `std::quoted("literal")` should be printable into any basic_ostream regardless of traits. Use hidden-friend `operator<<` and `operator>>`, since we're permitted to. (The exact signature is unspecified because the class itself is unspecified.) We shouldn't support `std::quoted("literal")` in C++03 or C++11 mode. (We do need `std::__quoted(s)` and `std::__quoted(cs)` in C++11 mode, because they're used by `std::__fs::filesystem::path`.) Differential Revision: https://reviews.llvm.org/D120135
This commit is contained in:
parent
0c2b43ab8c
commit
34206b869d
|
@ -66,6 +66,9 @@ API Changes
|
|||
(as an extension) ``__int128_t``, and the unsigned versions thereof.
|
||||
In particular, ``uniform_int_distribution<int8_t>`` is no longer supported.
|
||||
|
||||
- The C++14 function ``std::quoted(const char*)`` is no longer supported in
|
||||
C++03 or C++11 modes.
|
||||
|
||||
ABI Changes
|
||||
-----------
|
||||
|
||||
|
|
|
@ -1155,19 +1155,6 @@ size_t __do_string_hash(_Ptr __p, _Ptr __e)
|
|||
return __murmur2_or_cityhash<size_t>()(__p, (__e-__p)*sizeof(value_type));
|
||||
}
|
||||
|
||||
template <class _CharT, class _Iter, class _Traits = char_traits<_CharT> >
|
||||
struct __quoted_output_proxy
|
||||
{
|
||||
_Iter __first_;
|
||||
_Iter __last_;
|
||||
_CharT __delim_;
|
||||
_CharT __escape_;
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI
|
||||
explicit __quoted_output_proxy(_Iter __f, _Iter __l, _CharT __d, _CharT __e)
|
||||
: __first_(__f), __last_(__l), __delim_(__d), __escape_(__e) {}
|
||||
};
|
||||
|
||||
_LIBCPP_END_NAMESPACE_STD
|
||||
|
||||
_LIBCPP_POP_MACROS
|
||||
|
|
|
@ -513,10 +513,12 @@ put_time(const tm* __tm, const _CharT* __fmt)
|
|||
return __iom_t10<_CharT>(__tm, __fmt);
|
||||
}
|
||||
|
||||
template <class _CharT, class _Traits, class _ForwardIterator>
|
||||
basic_ostream<_CharT, _Traits>&
|
||||
#if _LIBCPP_STD_VER >= 11
|
||||
|
||||
template <class _CharT, class _Traits>
|
||||
_LIBCPP_HIDE_FROM_ABI basic_ostream<_CharT, _Traits>&
|
||||
__quoted_output(basic_ostream<_CharT, _Traits>& __os,
|
||||
_ForwardIterator __first, _ForwardIterator __last, _CharT __delim, _CharT __escape)
|
||||
const _CharT *__first, const _CharT *__last, _CharT __delim, _CharT __escape)
|
||||
{
|
||||
basic_string<_CharT, _Traits> __str;
|
||||
__str.push_back(__delim);
|
||||
|
@ -530,7 +532,7 @@ __quoted_output(basic_ostream<_CharT, _Traits>& __os,
|
|||
}
|
||||
|
||||
template <class _CharT, class _Traits, class _String>
|
||||
basic_istream<_CharT, _Traits>&
|
||||
_LIBCPP_HIDE_FROM_ABI basic_istream<_CharT, _Traits>&
|
||||
__quoted_input(basic_istream<_CharT, _Traits>& __is, _String& __string, _CharT __delim, _CharT __escape)
|
||||
{
|
||||
__string.clear();
|
||||
|
@ -546,7 +548,7 @@ __quoted_input(basic_istream<_CharT, _Traits>& __is, _String& __string, _CharT _
|
|||
return __is;
|
||||
}
|
||||
|
||||
__save_flags<_CharT, _Traits> sf(__is);
|
||||
__save_flags<_CharT, _Traits> __sf(__is);
|
||||
std::noskipws(__is);
|
||||
while (true) {
|
||||
__is >> __c;
|
||||
|
@ -563,16 +565,27 @@ __quoted_input(basic_istream<_CharT, _Traits>& __is, _String& __string, _CharT _
|
|||
return __is;
|
||||
}
|
||||
|
||||
template <class _CharT, class _Traits, class _Iter>
|
||||
basic_ostream<_CharT, _Traits>& operator<<(
|
||||
basic_ostream<_CharT, _Traits>& __os,
|
||||
const __quoted_output_proxy<_CharT, _Iter, _Traits>& __proxy)
|
||||
template <class _CharT, class _Traits>
|
||||
struct _LIBCPP_HIDDEN __quoted_output_proxy
|
||||
{
|
||||
return std::__quoted_output(__os, __proxy.__first_, __proxy.__last_, __proxy.__delim_, __proxy.__escape_);
|
||||
}
|
||||
const _CharT *__first_;
|
||||
const _CharT *__last_;
|
||||
_CharT __delim_;
|
||||
_CharT __escape_;
|
||||
|
||||
_LIBCPP_HIDE_FROM_ABI
|
||||
explicit __quoted_output_proxy(const _CharT *__f, const _CharT *__l, _CharT __d, _CharT __e)
|
||||
: __first_(__f), __last_(__l), __delim_(__d), __escape_(__e) {}
|
||||
|
||||
template<class _T2, __enable_if_t<_IsSame<_Traits, void>::value || _IsSame<_Traits, _T2>::value>* = nullptr>
|
||||
friend _LIBCPP_HIDE_FROM_ABI basic_ostream<_CharT, _T2>&
|
||||
operator<<(basic_ostream<_CharT, _T2>& __os, const __quoted_output_proxy& __p) {
|
||||
return std::__quoted_output(__os, __p.__first_, __p.__last_, __p.__delim_, __p.__escape_);
|
||||
}
|
||||
};
|
||||
|
||||
template <class _CharT, class _Traits, class _Allocator>
|
||||
struct __quoted_proxy
|
||||
struct _LIBCPP_HIDDEN __quoted_proxy
|
||||
{
|
||||
basic_string<_CharT, _Traits, _Allocator>& __string_;
|
||||
_CharT __delim_;
|
||||
|
@ -581,76 +594,66 @@ struct __quoted_proxy
|
|||
_LIBCPP_HIDE_FROM_ABI
|
||||
explicit __quoted_proxy(basic_string<_CharT, _Traits, _Allocator>& __s, _CharT __d, _CharT __e)
|
||||
: __string_(__s), __delim_(__d), __escape_(__e) {}
|
||||
|
||||
friend _LIBCPP_HIDE_FROM_ABI basic_ostream<_CharT, _Traits>&
|
||||
operator<<(basic_ostream<_CharT, _Traits>& __os, const __quoted_proxy& __p) {
|
||||
return std::__quoted_output(__os, __p.__string_.data(), __p.__string_.data() + __p.__string_.size(), __p.__delim_, __p.__escape_);
|
||||
}
|
||||
|
||||
friend _LIBCPP_HIDE_FROM_ABI basic_istream<_CharT, _Traits>&
|
||||
operator>>(basic_istream<_CharT, _Traits>& __is, const __quoted_proxy& __p) {
|
||||
return std::__quoted_input(__is, __p.__string_, __p.__delim_, __p.__escape_);
|
||||
}
|
||||
};
|
||||
|
||||
template <class _CharT, class _Traits, class _Allocator>
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
basic_ostream<_CharT, _Traits>& operator<<(
|
||||
basic_ostream<_CharT, _Traits>& __os,
|
||||
const __quoted_proxy<_CharT, _Traits, _Allocator>& __proxy)
|
||||
_LIBCPP_HIDE_FROM_ABI
|
||||
__quoted_output_proxy<_CharT, _Traits>
|
||||
__quoted(const basic_string<_CharT, _Traits, _Allocator>& __s, _CharT __delim = _CharT('"'), _CharT __escape = _CharT('\\'))
|
||||
{
|
||||
return std::__quoted_output(__os, __proxy.__string_.cbegin(), __proxy.__string_.cend(), __proxy.__delim_, __proxy.__escape_);
|
||||
}
|
||||
|
||||
// extractor for non-const basic_string& proxies
|
||||
template <class _CharT, class _Traits, class _Allocator>
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
basic_istream<_CharT, _Traits>& operator>>(
|
||||
basic_istream<_CharT, _Traits>& __is,
|
||||
const __quoted_proxy<_CharT, _Traits, _Allocator>& __proxy)
|
||||
{
|
||||
return std::__quoted_input(__is, __proxy.__string_, __proxy.__delim_, __proxy.__escape_);
|
||||
}
|
||||
|
||||
template <class _CharT>
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
__quoted_output_proxy<_CharT, const _CharT *>
|
||||
quoted(const _CharT *__s, _CharT __delim = _CharT('"'), _CharT __escape = _CharT('\\'))
|
||||
{
|
||||
const _CharT *__end = __s;
|
||||
while (*__end) ++__end;
|
||||
return __quoted_output_proxy<_CharT, const _CharT *>(__s, __end, __delim, __escape);
|
||||
return __quoted_output_proxy<_CharT, _Traits>(__s.data(), __s.data() + __s.size(), __delim, __escape);
|
||||
}
|
||||
|
||||
template <class _CharT, class _Traits, class _Allocator>
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
__quoted_output_proxy<_CharT, typename basic_string <_CharT, _Traits, _Allocator>::const_iterator>
|
||||
__quoted(const basic_string <_CharT, _Traits, _Allocator>& __s, _CharT __delim = _CharT('"'), _CharT __escape = _CharT('\\'))
|
||||
{
|
||||
return __quoted_output_proxy<_CharT, typename basic_string<_CharT, _Traits, _Allocator>::const_iterator>(__s.cbegin(), __s.cend(), __delim, __escape);
|
||||
}
|
||||
|
||||
template <class _CharT, class _Traits, class _Allocator>
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
_LIBCPP_HIDE_FROM_ABI
|
||||
__quoted_proxy<_CharT, _Traits, _Allocator>
|
||||
__quoted(basic_string <_CharT, _Traits, _Allocator>& __s, _CharT __delim = _CharT('"'), _CharT __escape = _CharT('\\'))
|
||||
__quoted(basic_string<_CharT, _Traits, _Allocator>& __s, _CharT __delim = _CharT('"'), _CharT __escape = _CharT('\\'))
|
||||
{
|
||||
return __quoted_proxy<_CharT, _Traits, _Allocator>(__s, __delim, __escape);
|
||||
}
|
||||
|
||||
#endif // _LIBCPP_STD_VER >= 11
|
||||
|
||||
#if _LIBCPP_STD_VER > 11
|
||||
|
||||
template <class _CharT, class _Traits, class _Allocator>
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
__quoted_output_proxy<_CharT, typename basic_string<_CharT, _Traits, _Allocator>::const_iterator>
|
||||
quoted(const basic_string<_CharT, _Traits, _Allocator>& __s, _CharT __delim = _CharT('"'), _CharT __escape = _CharT('\\'))
|
||||
template <class _CharT>
|
||||
_LIBCPP_HIDE_FROM_ABI
|
||||
auto quoted(const _CharT *__s, _CharT __delim = _CharT('"'), _CharT __escape = _CharT('\\'))
|
||||
{
|
||||
return std::__quoted(__s, __delim, __escape);
|
||||
const _CharT *__end = __s;
|
||||
while (*__end) ++__end;
|
||||
return __quoted_output_proxy<_CharT, void>(__s, __end, __delim, __escape);
|
||||
}
|
||||
|
||||
template <class _CharT, class _Traits, class _Allocator>
|
||||
_LIBCPP_INLINE_VISIBILITY
|
||||
__quoted_proxy<_CharT, _Traits, _Allocator>
|
||||
quoted(basic_string<_CharT, _Traits, _Allocator>& __s, _CharT __delim = _CharT('"'), _CharT __escape = _CharT('\\'))
|
||||
_LIBCPP_HIDE_FROM_ABI
|
||||
auto quoted(const basic_string<_CharT, _Traits, _Allocator>& __s, _CharT __delim = _CharT('"'), _CharT __escape = _CharT('\\'))
|
||||
{
|
||||
return std::__quoted(__s, __delim, __escape);
|
||||
return __quoted_output_proxy<_CharT, _Traits>(__s.data(), __s.data() + __s.size(), __delim, __escape);
|
||||
}
|
||||
|
||||
template <class _CharT, class _Traits, class _Allocator>
|
||||
_LIBCPP_HIDE_FROM_ABI
|
||||
auto quoted(basic_string<_CharT, _Traits, _Allocator>& __s, _CharT __delim = _CharT('"'), _CharT __escape = _CharT('\\'))
|
||||
{
|
||||
return __quoted_proxy<_CharT, _Traits, _Allocator>(__s, __delim, __escape);
|
||||
}
|
||||
|
||||
template <class _CharT, class _Traits>
|
||||
__quoted_output_proxy<_CharT, const _CharT *, _Traits>
|
||||
quoted(basic_string_view<_CharT, _Traits> __sv, _CharT __delim = _CharT('"'), _CharT __escape = _CharT('\\'))
|
||||
_LIBCPP_HIDE_FROM_ABI
|
||||
auto quoted(basic_string_view<_CharT, _Traits> __sv, _CharT __delim = _CharT('"'), _CharT __escape = _CharT('\\'))
|
||||
{
|
||||
return __quoted_output_proxy<_CharT, const _CharT *, _Traits>(__sv.data(), __sv.data() + __sv.size(), __delim, __escape);
|
||||
return __quoted_output_proxy<_CharT, _Traits>(__sv.data(), __sv.data() + __sv.size(), __delim, __escape);
|
||||
}
|
||||
|
||||
#endif // _LIBCPP_STD_VER > 11
|
||||
|
|
|
@ -0,0 +1,166 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++03, c++11
|
||||
|
||||
// <iomanip>
|
||||
|
||||
// std::quoted
|
||||
// Verify that the result type of std::quoted can be streamed to
|
||||
// (and from) ostreams with the correct CharTraits, and not those
|
||||
// with the wrong CharTraits. To avoid our having to create working
|
||||
// ostreams with weird CharTraits, this is a compile-only test.
|
||||
|
||||
#include <iomanip>
|
||||
#include <istream>
|
||||
#include <ostream>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <type_traits>
|
||||
|
||||
#include "test_allocator.h"
|
||||
#include "test_macros.h"
|
||||
|
||||
template<class IS, class Q>
|
||||
decltype(std::declval<IS>() >> std::declval<Q>(), std::true_type())
|
||||
has_rightshift_impl(int) { return std::true_type(); }
|
||||
|
||||
template<class IS, class Q>
|
||||
std::false_type
|
||||
has_rightshift_impl(long) { return std::false_type(); }
|
||||
|
||||
template<class IS, class Q>
|
||||
struct HasRightShift : decltype(has_rightshift_impl<IS, Q>(0)) {};
|
||||
|
||||
template<class OS, class Q>
|
||||
decltype(std::declval<OS>() << std::declval<Q>(), std::true_type())
|
||||
has_leftshift_impl(int) { return std::true_type(); }
|
||||
|
||||
template<class OS, class Q>
|
||||
std::false_type
|
||||
has_leftshift_impl(long) { return std::false_type(); }
|
||||
|
||||
template<class OS, class Q>
|
||||
struct HasLeftShift : decltype(has_leftshift_impl<OS, Q>(0)) {};
|
||||
|
||||
template<class CharT>
|
||||
struct FakeCharTraits : std::char_traits<CharT> {};
|
||||
|
||||
void test_string_literal()
|
||||
{
|
||||
using Q = decltype(std::quoted("hello"));
|
||||
static_assert( HasLeftShift<std::ostream&, Q>::value, "");
|
||||
static_assert(!HasRightShift<std::istream&, Q>::value, "");
|
||||
static_assert( HasLeftShift<std::basic_ostream<char, FakeCharTraits<char>>&, Q>::value, "");
|
||||
static_assert(!HasRightShift<std::basic_istream<char, FakeCharTraits<char>>&, Q>::value, "");
|
||||
|
||||
#ifndef TEST_HAS_NO_WIDE_CHARACTERS
|
||||
using WQ = decltype(std::quoted(L"hello"));
|
||||
static_assert( HasLeftShift<std::wostream&, WQ>::value, "");
|
||||
static_assert(!HasRightShift<std::wistream&, WQ>::value, "");
|
||||
static_assert( HasLeftShift<std::basic_ostream<wchar_t, FakeCharTraits<wchar_t>>&, WQ>::value, "");
|
||||
static_assert(!HasRightShift<std::basic_istream<wchar_t, FakeCharTraits<wchar_t>>&, WQ>::value, "");
|
||||
|
||||
static_assert(!HasLeftShift<std::ostream&, WQ>::value, "");
|
||||
static_assert(!HasLeftShift<std::wostream&, Q>::value, "");
|
||||
#endif // TEST_HAS_NO_WIDE_CHARACTERS
|
||||
}
|
||||
|
||||
void test_std_string()
|
||||
{
|
||||
std::string s = "hello";
|
||||
const auto& cs = s;
|
||||
using Q = decltype(std::quoted(s));
|
||||
using CQ = decltype(std::quoted(cs));
|
||||
static_assert( HasLeftShift<std::ostream&, Q>::value, "");
|
||||
static_assert( HasRightShift<std::istream&, Q>::value, "");
|
||||
static_assert( HasLeftShift<std::ostream&, CQ>::value, "");
|
||||
static_assert(!HasRightShift<std::istream&, CQ>::value, "");
|
||||
static_assert(!HasLeftShift<std::basic_ostream<char, FakeCharTraits<char>>&, Q>::value, "");
|
||||
static_assert(!HasRightShift<std::basic_istream<char, FakeCharTraits<char>>&, Q>::value, "");
|
||||
static_assert(!HasLeftShift<std::basic_ostream<char, FakeCharTraits<char>>&, CQ>::value, "");
|
||||
static_assert(!HasRightShift<std::basic_istream<char, FakeCharTraits<char>>&, CQ>::value, "");
|
||||
|
||||
std::basic_string<char, FakeCharTraits<char>, test_allocator<char>> st = "hello";
|
||||
const auto& cst = st;
|
||||
using QT = decltype(std::quoted(st));
|
||||
using CQT = decltype(std::quoted(cst));
|
||||
static_assert(!HasLeftShift<std::ostream&, QT>::value, "");
|
||||
static_assert(!HasRightShift<std::istream&, QT>::value, "");
|
||||
static_assert(!HasLeftShift<std::ostream&, CQT>::value, "");
|
||||
static_assert(!HasRightShift<std::istream&, CQT>::value, "");
|
||||
static_assert( HasLeftShift<std::basic_ostream<char, FakeCharTraits<char>>&, QT>::value, "");
|
||||
static_assert( HasRightShift<std::basic_istream<char, FakeCharTraits<char>>&, QT>::value, "");
|
||||
static_assert( HasLeftShift<std::basic_ostream<char, FakeCharTraits<char>>&, CQT>::value, "");
|
||||
static_assert(!HasRightShift<std::basic_istream<char, FakeCharTraits<char>>&, CQT>::value, "");
|
||||
|
||||
#ifndef TEST_HAS_NO_WIDE_CHARACTERS
|
||||
std::wstring ws = L"hello";
|
||||
const auto& cws = ws;
|
||||
using WQ = decltype(std::quoted(ws));
|
||||
using CWQ = decltype(std::quoted(cws));
|
||||
static_assert( HasLeftShift<std::wostream&, WQ>::value, "");
|
||||
static_assert( HasRightShift<std::wistream&, WQ>::value, "");
|
||||
static_assert( HasLeftShift<std::wostream&, CWQ>::value, "");
|
||||
static_assert(!HasRightShift<std::wistream&, CWQ>::value, "");
|
||||
static_assert(!HasLeftShift<std::basic_ostream<wchar_t, FakeCharTraits<wchar_t>>&, WQ>::value, "");
|
||||
static_assert(!HasRightShift<std::basic_istream<wchar_t, FakeCharTraits<wchar_t>>&, WQ>::value, "");
|
||||
static_assert(!HasLeftShift<std::basic_ostream<wchar_t, FakeCharTraits<wchar_t>>&, CWQ>::value, "");
|
||||
static_assert(!HasRightShift<std::basic_istream<wchar_t, FakeCharTraits<wchar_t>>&, CWQ>::value, "");
|
||||
|
||||
static_assert(!HasLeftShift<std::ostream&, WQ>::value, "");
|
||||
static_assert(!HasLeftShift<std::wostream&, Q>::value, "");
|
||||
#endif // TEST_HAS_NO_WIDE_CHARACTERS
|
||||
}
|
||||
|
||||
void test_std_string_view()
|
||||
{
|
||||
std::string_view s = "hello";
|
||||
const auto& cs = s;
|
||||
using Q = decltype(std::quoted(s));
|
||||
using CQ = decltype(std::quoted(cs));
|
||||
static_assert( HasLeftShift<std::ostream&, Q>::value, "");
|
||||
static_assert(!HasRightShift<std::istream&, Q>::value, "");
|
||||
static_assert( HasLeftShift<std::ostream&, CQ>::value, "");
|
||||
static_assert(!HasRightShift<std::istream&, CQ>::value, "");
|
||||
static_assert(!HasLeftShift<std::basic_ostream<char, FakeCharTraits<char>>&, Q>::value, "");
|
||||
static_assert(!HasRightShift<std::basic_istream<char, FakeCharTraits<char>>&, Q>::value, "");
|
||||
static_assert(!HasLeftShift<std::basic_ostream<char, FakeCharTraits<char>>&, CQ>::value, "");
|
||||
static_assert(!HasRightShift<std::basic_istream<char, FakeCharTraits<char>>&, CQ>::value, "");
|
||||
|
||||
std::basic_string_view<char, FakeCharTraits<char>> st = "hello";
|
||||
const auto& cst = st;
|
||||
using QT = decltype(std::quoted(st));
|
||||
using CQT = decltype(std::quoted(cst));
|
||||
static_assert(!HasLeftShift<std::ostream&, QT>::value, "");
|
||||
static_assert(!HasRightShift<std::istream&, QT>::value, "");
|
||||
static_assert(!HasLeftShift<std::ostream&, CQT>::value, "");
|
||||
static_assert(!HasRightShift<std::istream&, CQT>::value, "");
|
||||
static_assert( HasLeftShift<std::basic_ostream<char, FakeCharTraits<char>>&, QT>::value, "");
|
||||
static_assert(!HasRightShift<std::basic_istream<char, FakeCharTraits<char>>&, QT>::value, "");
|
||||
static_assert( HasLeftShift<std::basic_ostream<char, FakeCharTraits<char>>&, CQT>::value, "");
|
||||
static_assert(!HasRightShift<std::basic_istream<char, FakeCharTraits<char>>&, CQT>::value, "");
|
||||
|
||||
#ifndef TEST_HAS_NO_WIDE_CHARACTERS
|
||||
std::wstring_view ws = L"hello";
|
||||
const auto& cws = ws;
|
||||
using WQ = decltype(std::quoted(ws));
|
||||
using CWQ = decltype(std::quoted(cws));
|
||||
static_assert( HasLeftShift<std::wostream&, WQ>::value, "");
|
||||
static_assert(!HasRightShift<std::wistream&, WQ>::value, "");
|
||||
static_assert( HasLeftShift<std::wostream&, CWQ>::value, "");
|
||||
static_assert(!HasRightShift<std::wistream&, CWQ>::value, "");
|
||||
static_assert(!HasLeftShift<std::basic_ostream<wchar_t, FakeCharTraits<wchar_t>>&, WQ>::value, "");
|
||||
static_assert(!HasRightShift<std::basic_istream<wchar_t, FakeCharTraits<wchar_t>>&, WQ>::value, "");
|
||||
static_assert(!HasLeftShift<std::basic_ostream<wchar_t, FakeCharTraits<wchar_t>>&, CWQ>::value, "");
|
||||
static_assert(!HasRightShift<std::basic_istream<wchar_t, FakeCharTraits<wchar_t>>&, CWQ>::value, "");
|
||||
|
||||
static_assert(!HasLeftShift<std::ostream&, WQ>::value, "");
|
||||
static_assert(!HasLeftShift<std::wostream&, Q>::value, "");
|
||||
#endif // TEST_HAS_NO_WIDE_CHARACTERS
|
||||
}
|
Loading…
Reference in New Issue