32 std::same_as<T, char> || std::same_as<T, char8_t> || std::same_as<T, char16_t> || std::same_as<T, char32_t>
33 || std::same_as<T, signed char> || std::same_as<T, unsigned char>;
36 concept byte_like = std::same_as<std::decay_t<T>,
char> || std::same_as<std::decay_t<T>,
unsigned char>
37 || std::same_as<std::decay_t<T>,
signed char> || std::same_as<std::decay_t<T>, std::byte>;
39 template <builtin_
char_type T>
40 constexpr bool is_lower(T c)
noexcept {
41 return c >= T{
'a'} && c <= T{
'z'};
44 template <builtin_
char_type T>
45 constexpr bool is_upper(T c)
noexcept {
46 return c >= T{
'A'} && c <= T{
'Z'};
49 template <builtin_
char_type T>
50 constexpr T to_lower(T c)
noexcept {
51 return is_upper(c) ?
static_cast<T
>(c - T{
'A'} + T{
'a'}) : c;
54 template <builtin_
char_type T>
55 constexpr T to_upper(T c)
noexcept {
56 return is_lower(c) ?
static_cast<T
>(c - T{
'a'} + T{
'A'}) : c;