libstdc++: P1423R3 char8_t remediation (2/4)
Update feature test macro, add deleted operators, update u8path This patch increments the __cpp_lib_char8_t feature test macro, adds deleted operator<< overloads for basic_ostream, and modifies u8path to accept sequences of char8_t for both the C++17 implementation of std::filesystem, and the filesystem TS implementation. The implementation mechanism used for u8path differs between the C++17 and filesystem TS implementations. The changes to the former take advantage of C++17 'if constexpr'. The changes to the latter retain C++11 compatibility and rely on tag dispatching. 2019-11-29 Tom Honermann <tom@honermann.net> Update feature test macro, add deleted operators, update u8path * include/bits/c++config: Bumped the value of the __cpp_lib_char8_t feature test macro. * include/bits/fs_path.h (u8path): Modified u8path to accept sequences of char8_t. * include/experimental/bits/fs_path.h (u8path): Modified u8path to accept sequences of char8_t. * include/std/ostream: Added deleted overloads of wchar_t, char8_t, char16_t, and char32_t for ordinary and wide formatted character and string inserters. From-SVN: r278856
This commit is contained in:
parent
a1e7d33bb9
commit
2b4e2c93d9
@ -1,5 +1,16 @@
|
||||
2019-11-29 Tom Honermann <tom@honermann.net>
|
||||
|
||||
Update feature test macro, add deleted operators, update u8path
|
||||
* include/bits/c++config: Bumped the value of the __cpp_lib_char8_t
|
||||
feature test macro.
|
||||
* include/bits/fs_path.h (u8path): Modified u8path to accept sequences
|
||||
of char8_t.
|
||||
* include/experimental/bits/fs_path.h (u8path): Modified u8path to
|
||||
accept sequences of char8_t.
|
||||
* include/std/ostream: Added deleted overloads of wchar_t, char8_t,
|
||||
char16_t, and char32_t for ordinary and wide formatted character and
|
||||
string inserters.
|
||||
|
||||
Decouple constraints for u8path from path constructors
|
||||
* include/bits/fs_path.h: Moved helper utilities out of
|
||||
std::filesystem::path into a detail namespace to make them
|
||||
|
@ -620,7 +620,7 @@ namespace std
|
||||
# endif
|
||||
#endif
|
||||
#ifdef _GLIBCXX_USE_CHAR8_T
|
||||
# define __cpp_lib_char8_t 201811L
|
||||
# define __cpp_lib_char8_t 201907L
|
||||
#endif
|
||||
|
||||
/* Define if __float128 is supported on this host. */
|
||||
|
@ -154,9 +154,24 @@ namespace __detail
|
||||
|
||||
template<typename _Tp,
|
||||
typename _Iter = decltype(_S_range_begin(std::declval<_Tp>())),
|
||||
typename _Val = typename std::iterator_traits<_Iter>::value_type>
|
||||
typename _Val = typename std::iterator_traits<_Iter>::value_type,
|
||||
typename _UnqualVal = std::remove_const_t<_Val>>
|
||||
using __value_type_is_char
|
||||
= std::enable_if_t<std::is_same_v<std::remove_const_t<_Val>, char>>;
|
||||
= std::enable_if_t<std::is_same_v<_UnqualVal, char>,
|
||||
_UnqualVal>;
|
||||
|
||||
template<typename _Tp,
|
||||
typename _Iter = decltype(_S_range_begin(std::declval<_Tp>())),
|
||||
typename _Val = typename std::iterator_traits<_Iter>::value_type,
|
||||
typename _UnqualVal = std::remove_const_t<_Val>>
|
||||
using __value_type_is_char_or_char8_t
|
||||
= std::enable_if_t<__or_v<
|
||||
std::is_same<_UnqualVal, char>
|
||||
#ifdef _GLIBCXX_USE_CHAR8_T
|
||||
, std::is_same<_UnqualVal, char8_t>
|
||||
#endif
|
||||
>,
|
||||
_UnqualVal>;
|
||||
|
||||
} // namespace __detail
|
||||
/// @endcond
|
||||
@ -670,29 +685,41 @@ namespace __detail
|
||||
*/
|
||||
template<typename _InputIterator,
|
||||
typename _Require = __detail::_Path<_InputIterator, _InputIterator>,
|
||||
typename _Require2 = __detail::__value_type_is_char<_InputIterator>>
|
||||
typename _CharT
|
||||
= __detail::__value_type_is_char_or_char8_t<_InputIterator>>
|
||||
inline path
|
||||
u8path(_InputIterator __first, _InputIterator __last)
|
||||
{
|
||||
#ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS
|
||||
// XXX This assumes native wide encoding is UTF-16.
|
||||
std::codecvt_utf8_utf16<path::value_type> __cvt;
|
||||
path::string_type __tmp;
|
||||
if constexpr (is_pointer_v<_InputIterator>)
|
||||
#ifdef _GLIBCXX_USE_CHAR8_T
|
||||
if constexpr (is_same_v<_CharT, char8_t>)
|
||||
{
|
||||
if (__str_codecvt_in_all(__first, __last, __tmp, __cvt))
|
||||
return path{ __tmp };
|
||||
return path{ __first, __last };
|
||||
}
|
||||
else
|
||||
{
|
||||
const std::string __u8str{__first, __last};
|
||||
const char* const __ptr = __u8str.data();
|
||||
if (__str_codecvt_in_all(__ptr, __ptr + __u8str.size(), __tmp, __cvt))
|
||||
return path{ __tmp };
|
||||
#endif
|
||||
// XXX This assumes native wide encoding is UTF-16.
|
||||
std::codecvt_utf8_utf16<path::value_type> __cvt;
|
||||
path::string_type __tmp;
|
||||
if constexpr (is_pointer_v<_InputIterator>)
|
||||
{
|
||||
if (__str_codecvt_in_all(__first, __last, __tmp, __cvt))
|
||||
return path{ __tmp };
|
||||
}
|
||||
else
|
||||
{
|
||||
const std::string __u8str{__first, __last};
|
||||
const char* const __ptr = __u8str.data();
|
||||
if (__str_codecvt_in_all(__ptr, __ptr + __u8str.size(), __tmp, __cvt))
|
||||
return path{ __tmp };
|
||||
}
|
||||
_GLIBCXX_THROW_OR_ABORT(filesystem_error(
|
||||
"Cannot convert character sequence",
|
||||
std::make_error_code(errc::illegal_byte_sequence)));
|
||||
#ifdef _GLIBCXX_USE_CHAR8_T
|
||||
}
|
||||
_GLIBCXX_THROW_OR_ABORT(filesystem_error(
|
||||
"Cannot convert character sequence",
|
||||
std::make_error_code(errc::illegal_byte_sequence)));
|
||||
#endif
|
||||
#else
|
||||
// This assumes native normal encoding is UTF-8.
|
||||
return path{ __first, __last };
|
||||
@ -705,21 +732,32 @@ namespace __detail
|
||||
*/
|
||||
template<typename _Source,
|
||||
typename _Require = __detail::_Path<_Source>,
|
||||
typename _Require2 = __detail::__value_type_is_char<_Source>>
|
||||
typename _CharT = __detail::__value_type_is_char_or_char8_t<_Source>>
|
||||
inline path
|
||||
u8path(const _Source& __source)
|
||||
{
|
||||
#ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS
|
||||
if constexpr (is_convertible_v<const _Source&, std::string_view>)
|
||||
#ifdef _GLIBCXX_USE_CHAR8_T
|
||||
if constexpr (is_same_v<_CharT, char8_t>)
|
||||
{
|
||||
const std::string_view __s = __source;
|
||||
return filesystem::u8path(__s.data(), __s.data() + __s.size());
|
||||
return path{ __source };
|
||||
}
|
||||
else
|
||||
{
|
||||
std::string __s = path::_S_string_from_iter(__source);
|
||||
return filesystem::u8path(__s.data(), __s.data() + __s.size());
|
||||
#endif
|
||||
if constexpr (is_convertible_v<const _Source&, std::string_view>)
|
||||
{
|
||||
const std::string_view __s = __source;
|
||||
return filesystem::u8path(__s.data(), __s.data() + __s.size());
|
||||
}
|
||||
else
|
||||
{
|
||||
std::string __s = path::_S_string_from_iter(__source);
|
||||
return filesystem::u8path(__s.data(), __s.data() + __s.size());
|
||||
}
|
||||
#ifdef _GLIBCXX_USE_CHAR8_T
|
||||
}
|
||||
#endif
|
||||
#else
|
||||
return path{ __source };
|
||||
#endif
|
||||
|
@ -170,10 +170,23 @@ namespace __detail
|
||||
|
||||
template<typename _Tp,
|
||||
typename _Iter = decltype(_S_range_begin(std::declval<_Tp>())),
|
||||
typename _Val = typename std::iterator_traits<_Iter>::value_type>
|
||||
typename _Val = typename std::iterator_traits<_Iter>::value_type,
|
||||
typename _UnqualVal = typename std::remove_const<_Val>::type>
|
||||
using __value_type_is_char = typename std::enable_if<
|
||||
std::is_same<typename std::remove_const<_Val>::type, char>::value
|
||||
>::type;
|
||||
std::is_same<_UnqualVal, char>::value,
|
||||
_UnqualVal>::type;
|
||||
|
||||
template<typename _Tp,
|
||||
typename _Iter = decltype(_S_range_begin(std::declval<_Tp>())),
|
||||
typename _Val = typename std::iterator_traits<_Iter>::value_type,
|
||||
typename _UnqualVal = typename std::remove_const<_Val>::type>
|
||||
using __value_type_is_char_or_char8_t = typename std::enable_if<
|
||||
__or_<
|
||||
std::is_same<_UnqualVal, char>
|
||||
#ifdef _GLIBCXX_USE_CHAR8_T
|
||||
,std::is_same<_UnqualVal, char8_t>
|
||||
#endif
|
||||
>::value, _UnqualVal>::type;
|
||||
|
||||
} // namespace __detail
|
||||
/// @endcond
|
||||
@ -588,13 +601,11 @@ namespace __detail
|
||||
}
|
||||
|
||||
/// Create a path from a UTF-8-encoded sequence of char
|
||||
template<typename _InputIterator,
|
||||
typename _Require = __detail::_Path<_InputIterator, _InputIterator>,
|
||||
typename _Require2 = __detail::__value_type_is_char<_InputIterator>>
|
||||
inline path
|
||||
u8path(_InputIterator __first, _InputIterator __last)
|
||||
{
|
||||
#ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS
|
||||
template<typename _InputIterator>
|
||||
inline path
|
||||
__u8path(_InputIterator __first, _InputIterator __last, char)
|
||||
{
|
||||
// XXX This assumes native wide encoding is UTF-16.
|
||||
std::codecvt_utf8_utf16<path::value_type> __cvt;
|
||||
path::string_type __tmp;
|
||||
@ -605,21 +616,61 @@ namespace __detail
|
||||
_GLIBCXX_THROW_OR_ABORT(filesystem_error(
|
||||
"Cannot convert character sequence",
|
||||
std::make_error_code(errc::illegal_byte_sequence)));
|
||||
}
|
||||
|
||||
#ifdef _GLIBCXX_USE_CHAR8_T
|
||||
template<typename _InputIterator>
|
||||
inline path
|
||||
__u8path(_InputIterator __first, _InputIterator __last, char8_t)
|
||||
{
|
||||
return path{ __first, __last };
|
||||
}
|
||||
#endif // _GLIBCXX_USE_CHAR8_T
|
||||
#endif // _GLIBCXX_FILESYSTEM_IS_WINDOWS
|
||||
|
||||
template<typename _InputIterator,
|
||||
typename _Require = __detail::_Path<_InputIterator, _InputIterator>,
|
||||
typename _CharT =
|
||||
__detail::__value_type_is_char_or_char8_t<_InputIterator>>
|
||||
inline path
|
||||
u8path(_InputIterator __first, _InputIterator __last)
|
||||
{
|
||||
#ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS
|
||||
return __u8path(__first, __last, _CharT{});
|
||||
#else
|
||||
return path{ __first, __last };
|
||||
#endif
|
||||
}
|
||||
|
||||
/// Create a path from a UTF-8-encoded sequence of char
|
||||
#ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS
|
||||
template<typename _Source>
|
||||
inline path
|
||||
__u8path(const _Source& __source, char)
|
||||
{
|
||||
std::string __s = path::_S_string_from_iter(__source);
|
||||
return filesystem::u8path(__s.data(), __s.data() + __s.size());
|
||||
}
|
||||
|
||||
#ifdef _GLIBCXX_USE_CHAR8_T
|
||||
template<typename _Source>
|
||||
inline path
|
||||
__u8path(const _Source& __source, char8_t)
|
||||
{
|
||||
return path{ __source };
|
||||
}
|
||||
#endif // _GLIBCXX_USE_CHAR8_T
|
||||
#endif // _GLIBCXX_FILESYSTEM_IS_WINDOWS
|
||||
|
||||
template<typename _Source,
|
||||
typename _Require = __detail::_Path<_Source>,
|
||||
typename _Require2 = __detail::__value_type_is_char<_Source>>
|
||||
typename _CharT =
|
||||
__detail::__value_type_is_char_or_char8_t<_Source>>
|
||||
inline path
|
||||
u8path(const _Source& __source)
|
||||
{
|
||||
#ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS
|
||||
std::string __s = path::_S_string_from_iter(__source);
|
||||
return filesystem::u8path(__s.data(), __s.data() + __s.size());
|
||||
return __u8path(__source, _CharT{});
|
||||
#else
|
||||
return path{ __source };
|
||||
#endif
|
||||
|
@ -527,6 +527,47 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
inline basic_ostream<char, _Traits>&
|
||||
operator<<(basic_ostream<char, _Traits>& __out, unsigned char __c)
|
||||
{ return (__out << static_cast<char>(__c)); }
|
||||
|
||||
#if __cplusplus > 201703L
|
||||
// The following deleted overloads prevent formatting character values as
|
||||
// numeric values.
|
||||
|
||||
#ifdef _GLIBCXX_USE_WCHAR_T
|
||||
template<class _Traits>
|
||||
basic_ostream<char, _Traits>&
|
||||
operator<<(basic_ostream<char, _Traits>&, wchar_t) = delete;
|
||||
#endif // _GLIBCXX_USE_WCHAR_T
|
||||
|
||||
#ifdef _GLIBCXX_USE_CHAR8_T
|
||||
template<class _Traits>
|
||||
basic_ostream<char, _Traits>&
|
||||
operator<<(basic_ostream<char, _Traits>&, char8_t) = delete;
|
||||
#endif
|
||||
|
||||
template<class _Traits>
|
||||
basic_ostream<char, _Traits>&
|
||||
operator<<(basic_ostream<char, _Traits>&, char16_t) = delete;
|
||||
|
||||
template<class _Traits>
|
||||
basic_ostream<char, _Traits>&
|
||||
operator<<(basic_ostream<char, _Traits>&, char32_t) = delete;
|
||||
|
||||
#ifdef _GLIBCXX_USE_WCHAR_T
|
||||
#ifdef _GLIBCXX_USE_CHAR8_T
|
||||
template<class _Traits>
|
||||
basic_ostream<wchar_t, _Traits>&
|
||||
operator<<(basic_ostream<wchar_t, _Traits>&, char8_t) = delete;
|
||||
#endif // _GLIBCXX_USE_CHAR8_T
|
||||
|
||||
template<class _Traits>
|
||||
basic_ostream<wchar_t, _Traits>&
|
||||
operator<<(basic_ostream<wchar_t, _Traits>&, char16_t) = delete;
|
||||
|
||||
template<class _Traits>
|
||||
basic_ostream<wchar_t, _Traits>&
|
||||
operator<<(basic_ostream<wchar_t, _Traits>&, char32_t) = delete;
|
||||
#endif // _GLIBCXX_USE_WCHAR_T
|
||||
#endif // C++20
|
||||
//@}
|
||||
|
||||
//@{
|
||||
@ -582,6 +623,47 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
inline basic_ostream<char, _Traits> &
|
||||
operator<<(basic_ostream<char, _Traits>& __out, const unsigned char* __s)
|
||||
{ return (__out << reinterpret_cast<const char*>(__s)); }
|
||||
|
||||
#if __cplusplus > 201703L
|
||||
// The following deleted overloads prevent formatting strings as
|
||||
// pointer values.
|
||||
|
||||
#ifdef _GLIBCXX_USE_WCHAR_T
|
||||
template<class _Traits>
|
||||
basic_ostream<char, _Traits>&
|
||||
operator<<(basic_ostream<char, _Traits>&, const wchar_t*) = delete;
|
||||
#endif // _GLIBCXX_USE_WCHAR_T
|
||||
|
||||
#ifdef _GLIBCXX_USE_CHAR8_T
|
||||
template<class _Traits>
|
||||
basic_ostream<char, _Traits>&
|
||||
operator<<(basic_ostream<char, _Traits>&, const char8_t*) = delete;
|
||||
#endif // _GLIBCXX_USE_CHAR8_T
|
||||
|
||||
template<class _Traits>
|
||||
basic_ostream<char, _Traits>&
|
||||
operator<<(basic_ostream<char, _Traits>&, const char16_t*) = delete;
|
||||
|
||||
template<class _Traits>
|
||||
basic_ostream<char, _Traits>&
|
||||
operator<<(basic_ostream<char, _Traits>&, const char32_t*) = delete;
|
||||
|
||||
#ifdef _GLIBCXX_USE_WCHAR_T
|
||||
#ifdef _GLIBCXX_USE_CHAR8_T
|
||||
template<class _Traits>
|
||||
basic_ostream<wchar_t, _Traits>&
|
||||
operator<<(basic_ostream<wchar_t, _Traits>&, const char8_t*) = delete;
|
||||
#endif
|
||||
|
||||
template<class _Traits>
|
||||
basic_ostream<wchar_t, _Traits>&
|
||||
operator<<(basic_ostream<wchar_t, _Traits>&, const char16_t*) = delete;
|
||||
|
||||
template<class _Traits>
|
||||
basic_ostream<wchar_t, _Traits>&
|
||||
operator<<(basic_ostream<wchar_t, _Traits>&, const char32_t*) = delete;
|
||||
#endif // _GLIBCXX_USE_WCHAR_T
|
||||
#endif // C++20
|
||||
//@}
|
||||
|
||||
// Standard basic_ostream manipulators
|
||||
|
Loading…
x
Reference in New Issue
Block a user