3 #ifndef BOOST_HANA_CONFIG_ENABLE_STRING_UDL
4 #error "OZO needs BOOST_HANA_CONFIG_ENABLE_STRING_UDL to be defined"
7 #include <boost/fusion/adapted.hpp>
8 #include <boost/fusion/sequence.hpp>
9 #include <boost/fusion/support/is_sequence.hpp>
10 #include <boost/fusion/include/is_sequence.hpp>
11 #include <boost/hana/core/is_a.hpp>
12 #include <boost/hana/tuple.hpp>
13 #include <boost/hana/string.hpp>
15 #include <type_traits>
52 template <
bool Condition,
typename Type =
void>
53 #ifdef OZO_DOCUMENTATION
56 using Require = std::enable_if_t<Condition, Type>;
60 template <
typename T,
typename = std::
void_t<>>
61 struct has_operator_not : std::false_type {};
63 struct has_operator_not<T, std::void_t<decltype(!std::declval<T>())>>
75 inline constexpr
auto OperatorNot = has_operator_not<std::decay_t<T>>::value;
78 template <
typename T,
typename Enable =
void>
79 struct is_output_iterator : std::false_type {};
82 struct is_output_iterator<T, typename std::enable_if<
84 std::output_iterator_tag,
85 typename std::iterator_traits<T>::iterator_category
99 inline constexpr
auto OutputIterator = is_output_iterator<T>::value;
102 template <
typename T,
typename Enable =
void>
103 struct is_forward_iterator : std::false_type {};
105 template <
typename T>
106 struct is_forward_iterator<T, typename std::enable_if<
108 std::forward_iterator_tag,
109 typename std::iterator_traits<T>::iterator_category
121 template <
typename T>
126 template <
typename T,
typename Enable =
void>
127 struct is_iterable : std::false_type {};
129 template <
typename T>
130 struct is_iterable<T, typename std::enable_if<
131 is_forward_iterator<decltype(begin(std::declval<T>()))>::value &&
132 is_forward_iterator<decltype(end(std::declval<T>()))>::value
148 template <
typename T>
150 inline constexpr
auto Iterable = is_iterable<T>::value;
153 template <
typename T,
typename Enable =
void>
154 struct is_insert_iterator : std::false_type {};
156 template <
typename T>
157 struct is_insert_iterator<T, typename std::enable_if<
158 is_output_iterator<T>::value && std::is_class<typename T::container_type>::value
171 template <
typename T>
173 inline constexpr
auto InsertIterator = is_insert_iterator<T>::value;
182 template <
typename T>
184 inline constexpr
auto FusionSequence = boost::fusion::traits::is_sequence<std::decay_t<T>>::value;
193 template <
typename T>
195 inline constexpr
auto HanaSequence = boost::hana::Sequence<std::decay_t<T>>::value;
204 template <
typename T>
206 inline constexpr
auto HanaStruct = boost::hana::Struct<std::decay_t<T>>::value;
215 template <
typename T>
217 inline constexpr
auto HanaString = decltype(boost::hana::is_a<boost::hana::string_tag>(std::declval<T>()))::value;
226 template <
typename T>
228 inline constexpr
auto HanaTuple = decltype(boost::hana::is_a<boost::hana::tuple_tag>(std::declval<T>()))::value;
232 template <
typename T,
typename = std::
void_t<>>
233 struct is_fusion_adapted_struct : std::false_type {};
235 template <
typename T>
236 struct is_fusion_adapted_struct<T, std::enable_if_t<
238 typename boost::fusion::traits::tag_of<T>::type,
239 boost::fusion::struct_tag
241 >> : std::true_type {};
252 template <
typename T>
254 inline constexpr
auto FusionAdaptedStruct = is_fusion_adapted_struct<std::decay_t<T>>::value;
263 template <
typename T>
265 inline constexpr
auto Integral = std::is_integral_v<std::decay_t<T>>;
274 template <
typename T>
276 inline constexpr
auto FloatingPoint = std::is_floating_point_v<std::decay_t<T>>;
281 template <
typename T,
typename = std::
void_t<>>
282 struct std_size_data_compatible {
283 static constexpr
bool value =
false;
286 template <
typename T>
287 struct std_size_data_compatible<T, std::void_t<
288 decltype(std::data(std::declval<T&>())+std::size(std::declval<T&>()))>
290 static constexpr
bool value = !std::is_const_v<std::remove_pointer_t<decltype(std::data(std::declval<T&>()))>> || std::is_const_v<T>;
293 template <
typename T,
typename = std::
void_t<>>
294 struct adl_size_data_compatible {
295 static constexpr
bool value =
false;
298 template <
typename T>
299 struct adl_size_data_compatible<T, std::void_t<
300 decltype(data(std::declval<T&>())+size(std::declval<T&>()))>
302 static constexpr
bool value = !std::is_const_v<std::remove_pointer_t<decltype(data(std::declval<T&>()))>> || std::is_const_v<T>;
305 template <
typename T>
306 constexpr
auto sizeof_value_type(T& v) {
307 if constexpr (std_size_data_compatible<T>::value) {
308 return std::integral_constant<std::size_t,
sizeof(decltype(*std::data(v)))>{};
309 }
else if constexpr (adl_size_data_compatible<T>::value) {
310 return std::integral_constant<std::size_t,
sizeof(decltype(*data(v)))>{};
312 return std::integral_constant<std::size_t, 0>{};
316 template <
typename T>
317 constexpr std::size_t sizeof_value_type() {
318 return decltype(sizeof_value_type(std::declval<T&>()))::value;
323 template <
typename T>
324 using is_raw_data_writable = std::bool_constant<
325 !std::is_const_v<T> && detail::sizeof_value_type<T>() == 1
328 template <
typename T>
329 using is_raw_data_readable = std::bool_constant<
330 detail::sizeof_value_type<std::add_const_t<T>>() == 1
354 template <
typename T>
355 inline constexpr
auto RawDataWritable = is_raw_data_writable<std::remove_reference_t<T>>::value;
378 template <
typename T>
379 inline constexpr
auto RawDataReadable = is_raw_data_readable<std::remove_reference_t<T>>::value;
381 template <
typename T,
typename = std::
void_t<>>
382 struct is_emplaceable : std::false_type {};
384 template <
typename T>
385 struct is_emplaceable<T, std::void_t<decltype(std::declval<T&>().emplace())>> : std::true_type {};
394 template <
typename T>
395 inline constexpr
auto Emplaceable = is_emplaceable<std::decay_t<T>>::value;
397 template <
typename T>
398 struct is_time_constraint : std::false_type {};
413 template <
typename T>
415 inline constexpr
auto TimeConstraint = is_time_constraint<std::decay_t<T>>::value;