is_string_container.hpp 3.5 KB

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