Boost.Nowide
is_string_container.hpp
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 
7 #ifndef BOOST_NOWIDE_DETAIL_IS_STRING_CONTAINER_HPP_INCLUDED
8 #define BOOST_NOWIDE_DETAIL_IS_STRING_CONTAINER_HPP_INCLUDED
9 
10 #include <cstddef>
11 #include <type_traits>
12 
13 namespace boost {
14 namespace nowide {
15  namespace detail {
16  template<class...>
17  struct make_void
18  {
19  typedef void type;
20  };
21 
22  template<class... Ts>
23  using void_t = typename make_void<Ts...>::type;
24 
25  template<typename T>
26  struct is_char_type : std::false_type
27  {};
28  template<>
29  struct is_char_type<char> : std::true_type
30  {};
31  template<>
32  struct is_char_type<wchar_t> : std::true_type
33  {};
34  template<>
35  struct is_char_type<char16_t> : std::true_type
36  {};
37  template<>
38  struct is_char_type<char32_t> : std::true_type
39  {};
40 #ifdef __cpp_char8_t
41  template<>
42  struct is_char_type<char8_t> : std::true_type
43  {};
44 #endif
45 
46  template<typename T>
47  struct is_c_string : std::false_type
48  {};
49  template<typename T>
50  struct is_c_string<const T*> : is_char_type<T>
51  {};
52 
53  template<typename T>
54  using const_data_result = decltype(std::declval<const T>().data());
56  template<typename T>
57  using get_data_width =
58  std::integral_constant<std::size_t, sizeof(typename std::remove_pointer<const_data_result<T>>::type)>;
59  template<typename T>
60  using size_result = decltype(std::declval<T>().size());
62  template<typename T>
63  using has_narrow_data = std::integral_constant<bool, (get_data_width<T>::value == 1)>;
64 
68  template<typename T, bool isNarrow, typename = void>
69  struct is_string_container : std::false_type
70  {};
71  // clang-format off
72  template<typename T, bool isNarrow>
73  struct is_string_container<T, isNarrow, void_t<decltype(T::npos), size_result<T>, const_data_result<T>>>
74  : std::integral_constant<bool,
75  std::is_integral<decltype(T::npos)>::value
76  && std::is_integral<size_result<T>>::value
77  && is_c_string<const_data_result<T>>::value
78  && isNarrow == has_narrow_data<T>::value>
79  {};
80  // clang-format on
81  template<typename T>
82  using requires_narrow_string_container = typename std::enable_if<is_string_container<T, true>::value>::type;
83  template<typename T>
84  using requires_wide_string_container = typename std::enable_if<is_string_container<T, false>::value>::type;
85 
86  template<typename T>
87  using requires_narrow_char = typename std::enable_if<sizeof(T) == 1 && is_char_type<T>::value>::type;
88  template<typename T>
89  using requires_wide_char = typename std::enable_if<(sizeof(T) > 1) && is_char_type<T>::value>::type;
90 
91  } // namespace detail
92 } // namespace nowide
93 } // namespace boost
94 
95 #endif