diff --git a/include/seqan3/utility/char_operations/predicate_detail.hpp b/include/seqan3/utility/char_operations/predicate_detail.hpp index 02b0140539..8cefdc735b 100644 --- a/include/seqan3/utility/char_operations/predicate_detail.hpp +++ b/include/seqan3/utility/char_operations/predicate_detail.hpp @@ -19,6 +19,7 @@ #include #include +#include #include #include @@ -194,10 +195,21 @@ struct char_predicate_base constexpr bool operator()(value_t const val) const noexcept requires (sizeof(value_t) != 1) { - // std::char_traits is only defined for char types. libc++ deprecates other specialisations in llvm-17, and - // removes them in llvm-18. The int specialisation is needed for seqan3::is_eof(EOF). - using char_traits_value_t = std::conditional_t, char, value_t>; - using char_trait = std::char_traits; + // std::char_traits is only guaranteed to be defined for character types. + // libc++ deprecates other specialisations in llvm-17, and removes them in llvm-18. + // We map the non-character types to corresponding chracter types. + // For example, `seqan3::is_eof(EOF)` will call this function with `value_t == int`. + // clang-format off + using char_value_t = std::conditional_t, value_t, + std::conditional_t::int_type>, char, + std::conditional_t::int_type>, wchar_t, + std::conditional_t::int_type>, char8_t, + std::conditional_t::int_type>, char16_t, + std::conditional_t::int_type>, char32_t, + void>>>>>>; + // clang-format on + static_assert(!std::same_as, "There is no valid character representation."); + using char_trait = std::char_traits; return (static_cast>(val) < 256) ? operator()(static_cast(val)) : (char_trait::eq_int_type(val, char_trait::eof())) ? derived_t::data[256] : false; diff --git a/test/snippet/utility/char_operations/char_predicate.cpp b/test/snippet/utility/char_operations/char_predicate.cpp index 14a6c743a8..92f8c633a2 100644 --- a/test/snippet/utility/char_operations/char_predicate.cpp +++ b/test/snippet/utility/char_operations/char_predicate.cpp @@ -4,55 +4,55 @@ int main() { //! [is_eof] - static_assert(seqan3::is_eof(EOF)); // returns true - static_assert(!seqan3::is_eof('C')); // returns false + static_assert(seqan3::is_eof(EOF)); + static_assert(!seqan3::is_eof('C')); //! [is_eof] //! [is_cntrl] - static_assert(seqan3::is_cntrl('\0')); // returns true. + static_assert(seqan3::is_cntrl('\0')); //! [is_cntrl] //! [is_print] - static_assert(seqan3::is_print(' ')); // returns true. + static_assert(seqan3::is_print(' ')); //! [is_print] //! [is_space] - static_assert(seqan3::is_space('\n')); // returns true. + static_assert(seqan3::is_space('\n')); //! [is_space] //! [is_blank] - static_assert(seqan3::is_blank('\t')); // returns true. + static_assert(seqan3::is_blank('\t')); //! [is_blank] //! [is_graph] - static_assert(seqan3::is_graph('%')); // returns true. + static_assert(seqan3::is_graph('%')); //! [is_graph] //! [is_punct] - static_assert(seqan3::is_punct(':')); // returns true. + static_assert(seqan3::is_punct(':')); //! [is_punct] //! [is_alnum] - static_assert(seqan3::is_alnum('9')); // returns true. + static_assert(seqan3::is_alnum('9')); //! [is_alnum] //! [is_alpha] - static_assert(seqan3::is_alpha('z')); // returns true. + static_assert(seqan3::is_alpha('z')); //! [is_alpha] //! [is_upper] - static_assert(seqan3::is_upper('K')); // returns true. + static_assert(seqan3::is_upper('K')); //! [is_upper] //! [is_lower] - static_assert(seqan3::is_lower('a')); // returns true. + static_assert(seqan3::is_lower('a')); //! [is_lower] //! [is_digit] - static_assert(seqan3::is_digit('1')); // returns true. + static_assert(seqan3::is_digit('1')); //! [is_digit] //! [is_xdigit] - static_assert(seqan3::is_xdigit('e')); // returns true. + static_assert(seqan3::is_xdigit('e')); //! [is_xdigit] }