is_string_container.hpp 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596
  1. //
  2. // Copyright (c) 2020 Alexander Grund
  3. //
  4. // Distributed under the Boost Software License, Version 1.0. (See
  5. // accompanying file LICENSE or copy at
  6. // http://www.boost.org/LICENSE_1_0.txt)
  7. //
  8. #ifndef BOOST_NOWIDE_DETAIL_IS_STRING_CONTAINER_HPP_INCLUDED
  9. #define BOOST_NOWIDE_DETAIL_IS_STRING_CONTAINER_HPP_INCLUDED
  10. #include <cstddef>
  11. #include <type_traits>
  12. namespace boost {
  13. namespace nowide {
  14. namespace detail {
  15. template<class...>
  16. struct make_void
  17. {
  18. typedef void type;
  19. };
  20. template<class... Ts>
  21. using void_t = typename make_void<Ts...>::type;
  22. template<typename T>
  23. struct is_char_type : std::false_type
  24. {};
  25. template<>
  26. struct is_char_type<char> : std::true_type
  27. {};
  28. template<>
  29. struct is_char_type<wchar_t> : std::true_type
  30. {};
  31. template<>
  32. struct is_char_type<char16_t> : std::true_type
  33. {};
  34. template<>
  35. struct is_char_type<char32_t> : std::true_type
  36. {};
  37. #ifdef __cpp_char8_t
  38. template<>
  39. struct is_char_type<char8_t> : std::true_type
  40. {};
  41. #endif
  42. template<typename T>
  43. struct is_c_string : std::false_type
  44. {};
  45. template<typename T>
  46. struct is_c_string<const T*> : is_char_type<T>
  47. {};
  48. template<typename T>
  49. using const_data_result = decltype(std::declval<const T>().data());
  50. /// Return the size of the char type returned by the data() member function
  51. template<typename T>
  52. using get_data_width =
  53. std::integral_constant<std::size_t, sizeof(typename std::remove_pointer<const_data_result<T>>::type)>;
  54. template<typename T>
  55. using size_result = decltype(std::declval<T>().size());
  56. /// Return true if the data() member function returns a pointer to a type of size 1
  57. template<typename T>
  58. using has_narrow_data = std::integral_constant<bool, (get_data_width<T>::value == 1)>;
  59. /// Return true if T is a string container, e.g. std::basic_string, std::basic_string_view
  60. /// Requires a static value `npos`, a member function `size()` returning an integral,
  61. /// and a member function `data()` returning a C string
  62. template<typename T, bool isNarrow, typename = void>
  63. struct is_string_container : std::false_type
  64. {};
  65. // clang-format off
  66. template<typename T, bool isNarrow>
  67. struct is_string_container<T, isNarrow, void_t<decltype(T::npos), size_result<T>, const_data_result<T>>>
  68. : std::integral_constant<bool,
  69. std::is_integral<decltype(T::npos)>::value
  70. && std::is_integral<size_result<T>>::value
  71. && is_c_string<const_data_result<T>>::value
  72. && isNarrow == has_narrow_data<T>::value>
  73. {};
  74. // clang-format on
  75. template<typename T>
  76. using requires_narrow_string_container = typename std::enable_if<is_string_container<T, true>::value>::type;
  77. template<typename T>
  78. using requires_wide_string_container = typename std::enable_if<is_string_container<T, false>::value>::type;
  79. template<typename T>
  80. using requires_narrow_char = typename std::enable_if<sizeof(T) == 1 && is_char_type<T>::value>::type;
  81. template<typename T>
  82. using requires_wide_char = typename std::enable_if<(sizeof(T) > 1) && is_char_type<T>::value>::type;
  83. } // namespace detail
  84. } // namespace nowide
  85. } // namespace boost
  86. #endif