]>
Commit | Line | Data |
---|---|---|
1e59de90 TL |
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()); | |
56 | /// Return the size of the char type returned by the data() member function | |
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()); | |
62 | /// Return true if the data() member function returns a pointer to a type of size 1 | |
63 | template<typename T> | |
64 | using has_narrow_data = std::integral_constant<bool, (get_data_width<T>::value == 1)>; | |
65 | ||
66 | /// Return true if T is a string container, e.g. std::basic_string, std::basic_string_view | |
67 | /// Requires a static value `npos`, a member function `size()` returning an integral, | |
68 | /// and a member function `data()` returning a C string | |
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 |