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
13namespace boost {
14namespace 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