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