@@ -16,19 +16,19 @@ namespace utl | |||||
template<class X, class Enable = void> | template<class X, class Enable = void> | ||||
struct __impl_cop_is_value : | struct __impl_cop_is_value : | ||||
public mp::c_true { }; | |||||
public mp::c_true; | |||||
template<class X> | template<class X> | ||||
struct __impl_cop_is_value<X*, void> : | struct __impl_cop_is_value<X*, void> : | ||||
public mp::c_false { }; | |||||
public mp::c_false; | |||||
template<template<class> class F, class X> | template<template<class> class F, class X> | ||||
struct __impl_cop_is_value<F<X>, mp::enable_if<cop_is_base_of<smart_ptr<X>, F<X>>>> : | struct __impl_cop_is_value<F<X>, mp::enable_if<cop_is_base_of<smart_ptr<X>, F<X>>>> : | ||||
public mp::c_false { }; | |||||
public mp::c_false; | |||||
template<class X> | template<class X> | ||||
struct __impl_cop_is_value<std::reference_wrapper<X>, void> : | struct __impl_cop_is_value<std::reference_wrapper<X>, void> : | ||||
public mp::c_false { }; | |||||
public mp::c_false; | |||||
template<class X> | template<class X> | ||||
using cop_is_value = __impl_cop_is_value<mp::clean_type<X>>; | using cop_is_value = __impl_cop_is_value<mp::clean_type<X>>; | ||||
@@ -1,7 +1,7 @@ | |||||
#pragma once | #pragma once | ||||
#include <cpputils/mp/core.h> | #include <cpputils/mp/core.h> | ||||
#include <cpputils/mp/util.h> | |||||
#include <cpputils/mp/misc.h> | |||||
#include <cpputils/mp/intern.h> | #include <cpputils/mp/intern.h> | ||||
#include <cpputils/mp/container.h> | #include <cpputils/mp/container.h> | ||||
#include <cpputils/mp/operations.h> | #include <cpputils/mp/operations.h> |
@@ -1,3 +1,6 @@ | |||||
#pragma once | #pragma once | ||||
#include <cpputils/mp/container/pair.h> | |||||
#include <cpputils/mp/container/basic_tuple.h> | |||||
#include <cpputils/mp/container/map.h> | |||||
#include <cpputils/mp/container/pair.h> | |||||
#include <cpputils/mp/container/type.h> |
@@ -0,0 +1,159 @@ | |||||
#pragma once | |||||
#include <utility> | |||||
#include <cpputils/mp/core/modifier.h> | |||||
#include <cpputils/mp/core/conditionals.h> | |||||
#include <cpputils/mp/misc/make.h> | |||||
#include <cpputils/mp/misc/tag_of.h> | |||||
#include <cpputils/mp/intern/ebo.h> | |||||
#include <cpputils/mp/operations/at.h> | |||||
#include <cpputils/mp/operations/unpack.h> | |||||
#include <cpputils/mp/operations/transform.h> | |||||
namespace utl { | |||||
namespace mp { | |||||
struct tag_basic_tuple { }; | |||||
namespace __impl | |||||
{ | |||||
template<size_t> | |||||
struct basic_tuple_index; | |||||
template<typename Indices, typename... Xn> | |||||
struct basic_tuple_impl; | |||||
struct basic_tuple_from_other { }; | |||||
template<size_t... N, typename... Xn> | |||||
struct basic_tuple_impl<std::index_sequence<N...>, Xn...> | |||||
: intern::ebo<basic_tuple_index<N>, Xn>... | |||||
{ | |||||
static constexpr size_t _size = sizeof...(Xn); | |||||
constexpr basic_tuple_impl() = default; | |||||
template<typename Other> | |||||
explicit constexpr basic_tuple_impl(basic_tuple_from_other, Other&& other) | |||||
: intern::ebo<basic_tuple_index<N>, Xn>(intern::ebo_get<basic_tuple_index<N>>(std::forward<Other>(other)))... | |||||
{ } | |||||
template<typename... Yn> | |||||
explicit constexpr basic_tuple_impl(Yn&&... yn) | |||||
: intern::ebo<basic_tuple_index<N>, Xn>(std::forward<Yn>(yn))... | |||||
{ } | |||||
}; | |||||
} | |||||
template<typename... Xn> | |||||
struct basic_tuple final | |||||
: __impl::basic_tuple_impl<std::make_index_sequence<sizeof...(Xn)>, Xn...> | |||||
{ | |||||
using tag = tag_basic_tuple; | |||||
using base_type = __impl::basic_tuple_impl<std::make_index_sequence<sizeof...(Xn)>, Xn...>; | |||||
constexpr basic_tuple() = default; | |||||
template<typename Other, typename = enable_if<is_same<basic_tuple, decay_type<Other>>>> | |||||
constexpr basic_tuple(Other&& other) | |||||
: base_type(__impl::basic_tuple_from_other { }, std::forward<Other>(other)) | |||||
{ } | |||||
template<typename... Yn> | |||||
explicit constexpr basic_tuple(Yn&&... yn) | |||||
: base_type(std::forward<Yn>(yn)...) | |||||
{ } | |||||
template<typename N> | |||||
constexpr auto at(const N& n) const | |||||
{ return mp::at(*this, n); } | |||||
template<typename F> | |||||
constexpr auto unpack(F&& f) const | |||||
{ return mp::unpack(*this, std::forward<F>(f)); } | |||||
template<typename F> | |||||
constexpr auto transform(F&& f) const | |||||
{ return mp::transform(*this, std::forward<F>(f)); } | |||||
}; | |||||
constexpr auto make_basic_tuple = make<tag_basic_tuple>; | |||||
namespace __impl | |||||
{ | |||||
/* tag_of */ | |||||
template<typename... Xn> | |||||
struct tag_of_impl<basic_tuple<Xn...>> | |||||
{ using type = tag_basic_tuple; }; | |||||
/* make */ | |||||
template<> | |||||
struct make_impl<tag_basic_tuple> | |||||
{ | |||||
template<typename... Xn> | |||||
static constexpr auto apply(Xn&&... xn) | |||||
{ return basic_tuple<decay_type<Xn>...> { std::forward<Xn>(xn)... }; } | |||||
}; | |||||
/* unpack */ | |||||
template<> | |||||
struct unpack_impl<tag_basic_tuple> | |||||
{ | |||||
template<size_t... I, typename... Xn, typename F> | |||||
static constexpr auto apply(const basic_tuple_impl<std::index_sequence<I...>, Xn...>& xs, F&& f) | |||||
{ | |||||
return std::forward<F>(f)( | |||||
intern::ebo_get<basic_tuple_index<I>>( | |||||
static_cast<const intern::ebo<basic_tuple_index<I>, Xn>&>(xs) | |||||
)... | |||||
); | |||||
} | |||||
template<size_t... I, typename... Xn, typename F> | |||||
static constexpr auto apply(basic_tuple_impl<std::index_sequence<I...>, Xn...>& xs, F&& f) | |||||
{ | |||||
return std::forward<F>(f)( | |||||
intern::ebo_get<basic_tuple_index<I>>( | |||||
static_cast<intern::ebo<basic_tuple_index<I>, Xn>&>(xs) | |||||
)... | |||||
); | |||||
} | |||||
template<size_t... I, typename... Xn, typename F> | |||||
static constexpr auto apply(basic_tuple_impl<std::index_sequence<I...>, Xn...>&& xs, F&& f) | |||||
{ | |||||
return std::forward<F>(f)( | |||||
intern::ebo_get<basic_tuple_index<I>>( | |||||
static_cast<intern::ebo<basic_tuple_index<I>, Xn>&&>(xs) | |||||
)... | |||||
); | |||||
} | |||||
}; | |||||
/* at */ | |||||
template<> | |||||
struct at_impl<tag_basic_tuple> | |||||
{ | |||||
template<typename Xs, typename N> | |||||
static constexpr auto apply(Xs&& xs, const N&) | |||||
{ | |||||
constexpr size_t index = N::value; | |||||
return intern::ebo_get<basic_tuple_index<index>>(std::forward<Xs>(xs)); | |||||
} | |||||
}; | |||||
} | |||||
template <size_t N, typename... Xn> | |||||
constexpr auto at_c(const basic_tuple<Xn...>& x) | |||||
{ return intern::ebo_get<__impl::basic_tuple_index<N>>(x); } | |||||
template <size_t N, typename... Xn> | |||||
constexpr auto at_c(basic_tuple<Xn...>& x) | |||||
{ return intern::ebo_get<__impl::basic_tuple_index<N>>(x); } | |||||
template <size_t N, typename... Xn> | |||||
constexpr auto at_c(basic_tuple<Xn...>&& x) | |||||
{ return intern::ebo_get<__impl::basic_tuple_index<N>>(std::forward<basic_tuple<Xn...>>(x)); } | |||||
} | |||||
} |
@@ -0,0 +1,36 @@ | |||||
#pragma once | |||||
#include <cpputils/mp/misc/to.h> | |||||
#include <cpputils/mp/misc/make.h> | |||||
#include <cpputils/mp/container/basic_tuple.h> | |||||
namespace utl { | |||||
namespace mp { | |||||
struct tag_map { }; | |||||
constexpr auto make_map = make<tag_map>; | |||||
constexpr auto to_map = make<tag_map>; | |||||
namespace __impl /* forward declaration */ | |||||
{ | |||||
template<typename... Pairs> | |||||
struct make_map_type; | |||||
} | |||||
template<typename... Pairs> | |||||
using map = typename __impl::make_map_type<Pairs...>::type; | |||||
namespace __impl /* implementation */ | |||||
{ | |||||
template<typename... Pairs> | |||||
struct make_map_type | |||||
{ | |||||
using storage_type = basic_tuple<Pairs...>; | |||||
}; | |||||
} | |||||
} | |||||
} |
@@ -1,8 +1,8 @@ | |||||
#pragma once | #pragma once | ||||
#include <cpputils/mp/core.h> | #include <cpputils/mp/core.h> | ||||
#include <cpputils/mp/util/make.h> | |||||
#include <cpputils/mp/util/tag_of.h> | |||||
#include <cpputils/mp/misc/make.h> | |||||
#include <cpputils/mp/misc/tag_of.h> | |||||
#include <cpputils/mp/intern/ebo.h> | #include <cpputils/mp/intern/ebo.h> | ||||
#include <cpputils/mp/intern/operators_orderable.h> | #include <cpputils/mp/intern/operators_orderable.h> | ||||
#include <cpputils/mp/intern/operators_comparable.h> | #include <cpputils/mp/intern/operators_comparable.h> | ||||
@@ -33,6 +33,7 @@ namespace mp { | |||||
private intern::ebo<__impl::pair_index<0>, First>, | private intern::ebo<__impl::pair_index<0>, First>, | ||||
private intern::ebo<__impl::pair_index<1>, Second> | private intern::ebo<__impl::pair_index<1>, Second> | ||||
{ | { | ||||
using tag = tag_pair; | |||||
using this_type = pair<First, Second>; | using this_type = pair<First, Second>; | ||||
// default constructor | // default constructor | ||||
@@ -0,0 +1,268 @@ | |||||
#pragma once | |||||
#include <utility> | |||||
#include <cpputils/mp/misc/make.h> | |||||
#include <cpputils/mp/core/const.h> | |||||
#include <cpputils/mp/core/modifier.h> | |||||
#include <cpputils/mp/operations/hash.fwd.h> | |||||
#include <cpputils/mp/intern/operators_comparable.h> | |||||
namespace utl { | |||||
namespace mp { | |||||
namespace __impl /* forward declaration */ | |||||
{ | |||||
template<typename T> | |||||
struct type_impl; | |||||
struct decl_type_t | |||||
{ | |||||
template<typename T> | |||||
constexpr auto operator()(T&& t) const; | |||||
}; | |||||
struct type_id_t | |||||
{ | |||||
template <typename T> | |||||
constexpr auto operator()(T&&) const; | |||||
}; | |||||
struct size_of_t | |||||
{ | |||||
template <typename T> | |||||
constexpr auto operator()(T&&) const; | |||||
}; | |||||
struct align_of_t | |||||
{ | |||||
template <typename T> | |||||
constexpr auto operator()(T&&) const; | |||||
}; | |||||
struct is_valid_type_t | |||||
{ | |||||
template <typename F> | |||||
constexpr auto operator()(F&&) const; | |||||
template <typename F, typename ...Args> | |||||
constexpr auto operator()(F&&, Args&&...) const; | |||||
}; | |||||
template <template <typename ...> class F> | |||||
struct tmplt_t; | |||||
template <template <typename ...> class F> | |||||
struct metafunction_t; | |||||
template <typename F> | |||||
struct metafunction_class_t | |||||
: metafunction_t<F::template apply> | |||||
{ }; | |||||
template <typename F> | |||||
struct integral_t; | |||||
struct make_integral_t | |||||
{ | |||||
template <typename F> | |||||
constexpr integral_t<F> operator()(F const&) const | |||||
{ return { }; } | |||||
}; | |||||
} | |||||
struct tag_type { }; | |||||
template<typename T> | |||||
using type = typename __impl::type_impl<T>::type; | |||||
template<typename T> | |||||
constexpr type<T> type_c { }; | |||||
constexpr auto make_mp_type = make<tag_type>; | |||||
constexpr __impl::decl_type_t decl_type { }; | |||||
constexpr __impl::type_id_t type_id { }; | |||||
constexpr __impl::size_of_t size_of { }; | |||||
constexpr __impl::align_of_t align_of { }; | |||||
constexpr __impl::is_valid_type_t is_valid_type { }; | |||||
template <template <typename ...> class F> | |||||
constexpr __impl::tmplt_t<F> tmplt { }; | |||||
template <template <typename ...> class F> | |||||
constexpr __impl::metafunction_t<F> metafunction { }; | |||||
template <typename F> | |||||
constexpr __impl::metafunction_class_t<F> metafunction_class { }; | |||||
constexpr __impl::make_integral_t integral { }; | |||||
template <template <typename ...> class F> | |||||
constexpr auto trait = integral(metafunction<F>); | |||||
namespace __impl /* implementation */ | |||||
{ | |||||
/* basic_type */ | |||||
template<typename T> | |||||
struct basic_type | |||||
{ | |||||
using tag = tag_type; | |||||
using type = T; | |||||
constexpr auto operator+() const | |||||
{ return *this; } | |||||
}; | |||||
/* type */ | |||||
template<typename T> | |||||
struct type_impl | |||||
{ | |||||
struct type : basic_type<T> | |||||
{ }; | |||||
}; | |||||
/* decl_type */ | |||||
template <typename T, typename = tag_type> | |||||
struct decltype_helper | |||||
{ using type = remove_ref<T>; }; | |||||
template <typename T> | |||||
struct decltype_helper<T, tag_of<T>> | |||||
{ using type = typename remove_ref<T>::type; }; | |||||
template<typename T> | |||||
constexpr auto decl_type_t::operator()(T&& t) const | |||||
{ return type_c<typename decltype_helper<T>::type>; } | |||||
/* type_id */ | |||||
template <typename T, typename = tag_type> | |||||
struct typeid_helper | |||||
{ using type = clean_type<T>; }; | |||||
template <typename T> | |||||
struct typeid_helper<T, tag_of<T>> | |||||
{ using type = typename remove_ref<T>::type; }; | |||||
template <typename T> | |||||
constexpr auto type_id_t::operator()(T&&) const | |||||
{ return type_c<typename typeid_helper<T>::type>; } | |||||
/* make */ | |||||
template <> | |||||
struct make_impl<tag_type> | |||||
{ | |||||
template <typename T> | |||||
static constexpr auto apply(T&& t) | |||||
{ return type_id(std::forward<T>(t)); } | |||||
}; | |||||
/* size_of */ | |||||
template <typename T> | |||||
constexpr auto size_of_t::operator()(T&&) const | |||||
{ return c_size_t<sizeof(typename decltype_helper<T>::type)> { }; } | |||||
/* align_of */ | |||||
template <typename T> | |||||
constexpr auto align_of_t::operator()(T&&) const | |||||
{ return c_size_t<alignof(typename decltype_helper<T>::type)> { }; } | |||||
/* is_valid_type */ | |||||
template<typename F, typename... Args, typename = decltype(std::declval<F&&>()(std::declval<Args&&>()...))> | |||||
constexpr auto is_valid_type_impl(int) | |||||
{ return c_true; } | |||||
template<typename F, typename... Args> | |||||
constexpr auto is_valid_type_impl(...) | |||||
{ return c_false; } | |||||
template<typename F> | |||||
struct is_valid_type_helper | |||||
{ | |||||
template<typename... Args> | |||||
constexpr auto operator()(Args&&...) const | |||||
{ return is_valid_type_impl<F, Args&&...>(int { }); } | |||||
}; | |||||
template <typename F> | |||||
constexpr auto is_valid_type_t::operator()(F&&) const | |||||
{ return is_valid_type_helper<F&&> { }; } | |||||
template <typename F, typename ...Args> | |||||
constexpr auto is_valid_type_t::operator()(F&&, Args&&...) const | |||||
{ return is_valid_type_impl<F&&, Args&&...>(int { }); } | |||||
/* tmplt */ | |||||
template <template <typename ...> class F> | |||||
struct tmplt_t | |||||
{ | |||||
template<typename... T> | |||||
struct apply | |||||
{ using type = F<T...>; }; | |||||
template<typename... T> | |||||
constexpr auto operator()(const T&...) const | |||||
{ return type<F<typename T::type...>> { }; } | |||||
}; | |||||
/* metafunction */ | |||||
template <template <typename ...> class F> | |||||
struct metafunction_t | |||||
{ | |||||
template<typename... T> | |||||
using apply = F<T...>; | |||||
template<typename... T> | |||||
constexpr type<typename F<typename T::type...>::type> operator()(const T&...) const | |||||
{ return { }; } | |||||
}; | |||||
/* integral */ | |||||
template <typename F> | |||||
struct integral_t | |||||
{ | |||||
template<typename... T> | |||||
constexpr auto operator()(const T& ...) const | |||||
{ | |||||
using result_type = typename F::template apply<typename T::type...>::type; | |||||
return result_type { }; | |||||
} | |||||
}; | |||||
/* equal */ | |||||
template <> | |||||
struct equal_impl<tag_type, tag_type> | |||||
{ | |||||
template <typename T, typename U> | |||||
static constexpr auto apply(const basic_type<T>&, const basic_type<U>&) | |||||
{ return c_false; } | |||||
template <typename T> | |||||
static constexpr auto apply(const basic_type<T>&, const basic_type<T>&) | |||||
{ return c_true; } | |||||
}; | |||||
/* hash */ | |||||
template<> | |||||
struct hash_impl<tag_type> | |||||
{ | |||||
template <typename T> | |||||
static constexpr T apply(const T& t) | |||||
{ return t; } | |||||
}; | |||||
} | |||||
namespace intern { | |||||
template<> | |||||
struct operators_comparable<tag_type> | |||||
{ static constexpr bool value = true; }; | |||||
} | |||||
} | |||||
} |
@@ -13,37 +13,43 @@ namespace mp { | |||||
} | } | ||||
template<typename T, typename S> | template<typename T, typename S> | ||||
using is_same = c_bool<std::is_same<T, S>::value>; | |||||
using is_same = c_bool_t<std::is_same<T, S>::value>; | |||||
template<typename Base, typename Derived> | template<typename Base, typename Derived> | ||||
using is_base_of = c_bool<std::is_base_of<Base, Derived>::value>; | |||||
using is_base_of = c_bool_t<std::is_base_of<Base, Derived>::value>; | |||||
template<typename... T> | template<typename... T> | ||||
using is_constructible = c_bool<std::is_constructible<T...>::value>; | |||||
using is_constructible = c_bool_t<std::is_constructible<T...>::value>; | |||||
template<typename... T> | template<typename... T> | ||||
using is_empty = c_bool<std::is_empty<T...>::value>; | |||||
using is_empty = c_bool_t<std::is_empty<T...>::value>; | |||||
template<typename... T> | template<typename... T> | ||||
using is_final = c_bool<std::is_final<T...>::value>; | |||||
using is_final = c_bool_t<std::is_final<T...>::value>; | |||||
template<typename T, typename U> | template<typename T, typename U> | ||||
using is_convertible = c_bool<std::is_convertible<T, U>::value>; | |||||
using is_convertible = c_bool_t<std::is_convertible<T, U>::value>; | |||||
template<typename T, typename U> | template<typename T, typename U> | ||||
using is_assignable = c_bool<std::is_assignable<T, U>::value>; | |||||
using is_assignable = c_bool_t<std::is_assignable<T, U>::value>; | |||||
template<typename... T> | template<typename... T> | ||||
using is_valid = __impl::is_valid_impl<T...>; | using is_valid = __impl::is_valid_impl<T...>; | ||||
template<typename T> | template<typename T> | ||||
using is_arithmetic = c_bool<std::is_arithmetic<T>::value>; | |||||
using is_arithmetic = c_bool_t<std::is_arithmetic<T>::value>; | |||||
template<typename T> | |||||
using is_signed = c_bool_t<std::is_signed<T>::value>; | |||||
template<typename T> | |||||
using is_unsigned = c_bool_t<std::is_unsigned<T>::value>; | |||||
namespace __impl /* implementation */ | namespace __impl /* implementation */ | ||||
{ | { | ||||
template<typename...> | template<typename...> | ||||
struct is_valid_impl : | struct is_valid_impl : | ||||
public c_true | |||||
public c_true_t | |||||
{ }; | { }; | ||||
} | } | ||||
@@ -7,24 +7,31 @@ namespace utl { | |||||
namespace mp { | namespace mp { | ||||
template<typename T> | template<typename T> | ||||
struct tag_const { }; | |||||
struct tag_integral_constant { }; | |||||
template<typename T, T t> | template<typename T, T t> | ||||
struct integral_constant : | struct integral_constant : | ||||
public std::integral_constant<T, t> | public std::integral_constant<T, t> | ||||
{ | { | ||||
using tag = tag_const<T>; | |||||
using tag = tag_integral_constant<T>; | |||||
}; | }; | ||||
template<bool B> | template<bool B> | ||||
using c_bool = integral_constant<bool, B>; | |||||
using c_bool_t = integral_constant<bool, B>; | |||||
template<size_t S> | template<size_t S> | ||||
using c_size_t = integral_constant<size_t, S>; | using c_size_t = integral_constant<size_t, S>; | ||||
using c_true = c_bool<true>; | |||||
using c_false = c_bool<false>; | |||||
using c_zero = c_size_t<0>; | |||||
using c_zero_t = c_size_t<0>; | |||||
using c_true_t = c_bool_t<true>; | |||||
using c_false_t = c_bool_t<false>; | |||||
template<size_t S> | |||||
constexpr c_size_t<S> c_size { }; | |||||
constexpr c_zero_t c_zero { }; | |||||
constexpr c_true_t c_true { }; | |||||
constexpr c_false_t c_false { }; | |||||
} | } | ||||
} | } |
@@ -1,3 +1,11 @@ | |||||
#pragma once | #pragma once | ||||
#include <cpputils/mp/intern/ebo.h> | |||||
#include <cpputils/mp/intern/comparable_equal.h> | |||||
#include <cpputils/mp/intern/comparable_less.h> | |||||
#include <cpputils/mp/intern/ebo.h> | |||||
#include <cpputils/mp/intern/fold_left.h> | |||||
#include <cpputils/mp/intern/fold_right.h> | |||||
#include <cpputils/mp/intern/has_value.h> | |||||
#include <cpputils/mp/intern/hash_table.h> | |||||
#include <cpputils/mp/intern/operators_comparable.h> | |||||
#include <cpputils/mp/intern/operators_orderable.h> |
@@ -9,14 +9,14 @@ namespace intern { | |||||
template<typename T, typename U = T, typename = void> | template<typename T, typename U = T, typename = void> | ||||
struct comparable_equal | struct comparable_equal | ||||
: c_false | |||||
: c_false_t | |||||
{ }; | { }; | ||||
template<typename T> | template<typename T> | ||||
struct comparable_equal<T, T, void_t< | struct comparable_equal<T, T, void_t< | ||||
decltype(std::forward<T>(std::declval<T>()) == std::forward<T>(std::declval<T>()) ? 0 : 0), | decltype(std::forward<T>(std::declval<T>()) == std::forward<T>(std::declval<T>()) ? 0 : 0), | ||||
decltype(std::forward<T>(std::declval<T>()) != std::forward<T>(std::declval<T>()) ? 0 : 0)>> | decltype(std::forward<T>(std::declval<T>()) != std::forward<T>(std::declval<T>()) ? 0 : 0)>> | ||||
: c_true | |||||
: c_true_t | |||||
{ }; | { }; | ||||
template <typename T, typename U> | template <typename T, typename U> | ||||
@@ -28,7 +28,7 @@ namespace intern { | |||||
decltype(std::forward<T>(std::declval<T>()) != std::forward<U>(std::declval<U>()) ? 0 : 0), | decltype(std::forward<T>(std::declval<T>()) != std::forward<U>(std::declval<U>()) ? 0 : 0), | ||||
decltype(std::forward<U>(std::declval<U>()) != std::forward<T>(std::declval<T>()) ? 0 : 0), | decltype(std::forward<U>(std::declval<U>()) != std::forward<T>(std::declval<T>()) ? 0 : 0), | ||||
common_type<T, U>>>> | common_type<T, U>>>> | ||||
: c_bool< | |||||
: c_bool_t< | |||||
comparable_equal<T>::value && | comparable_equal<T>::value && | ||||
comparable_equal<U>::value && | comparable_equal<U>::value && | ||||
comparable_equal<common_type<T, U>>::value> | comparable_equal<common_type<T, U>>::value> | ||||
@@ -9,13 +9,13 @@ namespace intern { | |||||
template<typename T, typename U = T, typename = void> | template<typename T, typename U = T, typename = void> | ||||
struct comparable_less | struct comparable_less | ||||
: c_false | |||||
: c_false_t | |||||
{ }; | { }; | ||||
template<typename T> | template<typename T> | ||||
struct comparable_less<T, T, void_t< | struct comparable_less<T, T, void_t< | ||||
decltype(std::forward<T>(std::declval<T>()) < std::forward<T>(std::declval<T>()) ? 0 : 0)>> | decltype(std::forward<T>(std::declval<T>()) < std::forward<T>(std::declval<T>()) ? 0 : 0)>> | ||||
: c_true | |||||
: c_true_t | |||||
{ }; | { }; | ||||
template <typename T, typename U> | template <typename T, typename U> | ||||
@@ -25,7 +25,7 @@ namespace intern { | |||||
decltype(std::forward<T>(std::declval<T>()) < std::forward<U>(std::declval<U>()) ? 0 : 0), | decltype(std::forward<T>(std::declval<T>()) < std::forward<U>(std::declval<U>()) ? 0 : 0), | ||||
decltype(std::forward<U>(std::declval<U>()) < std::forward<T>(std::declval<T>()) ? 0 : 0), | decltype(std::forward<U>(std::declval<U>()) < std::forward<T>(std::declval<T>()) ? 0 : 0), | ||||
common_type<T, U>>>> | common_type<T, U>>>> | ||||
: c_bool< | |||||
: c_bool_t< | |||||
comparable_less<T>::value && | comparable_less<T>::value && | ||||
comparable_less<U>::value && | comparable_less<U>::value && | ||||
comparable_less<common_type<T, U>>::value> | comparable_less<common_type<T, U>>::value> | ||||
@@ -0,0 +1,265 @@ | |||||
#pragma once | |||||
#include <utility> | |||||
#include <cpputils/mp/misc/when.h> | |||||
namespace utl { | |||||
namespace mp { | |||||
namespace intern { | |||||
namespace __impl | |||||
{ | |||||
template <unsigned int n, typename = when<true>> | |||||
struct fold_left_impl; | |||||
template<> | |||||
struct fold_left_impl<1> | |||||
{ | |||||
template<typename F, typename X1> | |||||
static constexpr X1 apply(F&&, X1&& x1) | |||||
{ return std::forward<X1>(x1); } | |||||
}; | |||||
template<> | |||||
struct fold_left_impl<2> | |||||
{ | |||||
template<typename F, typename X1, typename X2> | |||||
static constexpr auto apply(F&& f, X1&& x1, X2&& x2) | |||||
{ | |||||
return f( | |||||
std::forward<X1>(x1), | |||||
std::forward<X2>(x2)); | |||||
} | |||||
}; | |||||
template<> | |||||
struct fold_left_impl<3> | |||||
{ | |||||
template<typename F, typename X1, typename X2, typename X3> | |||||
static constexpr auto apply(F&& f, X1&& x1, X2&& x2, X3&& x3) | |||||
{ | |||||
return f(f( | |||||
std::forward<X1>(x1), | |||||
std::forward<X2>(x2)), | |||||
std::forward<X3>(x3)); | |||||
} | |||||
}; | |||||
template<> | |||||
struct fold_left_impl<4> | |||||
{ | |||||
template<typename F, typename X1, typename X2, typename X3, typename X4> | |||||
static constexpr auto apply(F&& f, X1&& x1, X2&& x2, X3&& x3, X4&& x4) | |||||
{ | |||||
return f(f(f( | |||||
std::forward<X1>(x1), | |||||
std::forward<X2>(x2)), | |||||
std::forward<X3>(x3)), | |||||
std::forward<X4>(x4)); | |||||
} | |||||
}; | |||||
template<> | |||||
struct fold_left_impl<5> | |||||
{ | |||||
template<typename F, typename X1, typename X2, typename X3, typename X4, typename X5> | |||||
static constexpr auto apply(F&& f, X1&& x1, X2&& x2, X3&& x3, X4&& x4, X5&& x5) | |||||
{ | |||||
return f(f(f(f( | |||||
std::forward<X1>(x1), | |||||
std::forward<X2>(x2)), | |||||
std::forward<X3>(x3)), | |||||
std::forward<X4>(x4)), | |||||
std::forward<X5>(x5)); | |||||
} | |||||
}; | |||||
template<> | |||||
struct fold_left_impl<6> | |||||
{ | |||||
template<typename F, typename X1, typename X2, typename X3, typename X4, typename X5, typename X6> | |||||
static constexpr auto apply(F&& f, X1&& x1, X2&& x2, X3&& x3, X4&& x4, X5&& x5, X6&& x6) | |||||
{ | |||||
return f(f(f(f(f( | |||||
std::forward<X1>(x1), | |||||
std::forward<X2>(x2)), | |||||
std::forward<X3>(x3)), | |||||
std::forward<X4>(x4)), | |||||
std::forward<X5>(x5)), | |||||
std::forward<X6>(x6)); | |||||
} | |||||
}; | |||||
template<> | |||||
struct fold_left_impl<7> | |||||
{ | |||||
template<typename F, typename X1, typename X2, typename X3, typename X4, typename X5, typename X6, typename X7> | |||||
static constexpr auto apply(F&& f, X1&& x1, X2&& x2, X3&& x3, X4&& x4, X5&& x5, X6&& x6, X7&& x7) | |||||
{ | |||||
return f(f(f(f(f(f( | |||||
std::forward<X1>(x1), | |||||
std::forward<X2>(x2)), | |||||
std::forward<X3>(x3)), | |||||
std::forward<X4>(x4)), | |||||
std::forward<X5>(x5)), | |||||
std::forward<X6>(x6)), | |||||
std::forward<X7>(x7)); | |||||
} | |||||
}; | |||||
template<> | |||||
struct fold_left_impl<8> | |||||
{ | |||||
template<typename F, typename X1, typename X2, typename X3, typename X4, typename X5, typename X6, typename X7, typename X8> | |||||
static constexpr auto apply(F&& f, X1&& x1, X2&& x2, X3&& x3, X4&& x4, X5&& x5, X6&& x6, X7&& x7, X8&& x8) | |||||
{ | |||||
return f(f(f(f(f(f(f( | |||||
std::forward<X1>(x1), | |||||
std::forward<X2>(x2)), | |||||
std::forward<X3>(x3)), | |||||
std::forward<X4>(x4)), | |||||
std::forward<X5>(x5)), | |||||
std::forward<X6>(x6)), | |||||
std::forward<X7>(x7)), | |||||
std::forward<X8>(x8)); | |||||
} | |||||
}; | |||||
template<unsigned int n> | |||||
struct fold_left_impl<n, when<(n >= 9) && (n < 18)>> | |||||
{ | |||||
template<typename F, typename X1, typename X2, typename X3, typename X4, typename X5, typename X6, typename X7, typename X8, typename X9, typename... Xn> | |||||
static constexpr auto apply(F&& f, X1&& x1, X2&& x2, X3&& x3, X4&& x4, X5&& x5, X6&& x6, X7&& x7, X8&& x8, X9&& x9, Xn&&... xn) | |||||
{ | |||||
return fold_left_impl<sizeof...(xn) + 1>::apply( | |||||
f, | |||||
f(f(f(f(f(f(f(f( | |||||
std::forward<X1>(x1), | |||||
std::forward<X2>(x2)), | |||||
std::forward<X3>(x3)), | |||||
std::forward<X4>(x4)), | |||||
std::forward<X5>(x5)), | |||||
std::forward<X6>(x6)), | |||||
std::forward<X7>(x7)), | |||||
std::forward<X8>(x8)), | |||||
std::forward<X9>(x9)), | |||||
std::forward<Xn>(xn)... | |||||
); | |||||
} | |||||
}; | |||||
template<unsigned int n> | |||||
struct fold_left_impl<n, when<(n >= 18) && (n < 36)>> | |||||
{ | |||||
template< | |||||
typename F, | |||||
typename X1, typename X2, typename X3, typename X4, typename X5, typename X6, typename X7, typename X8, typename X9, | |||||
typename X10, typename X11, typename X12, typename X13, typename X14, typename X15, typename X16, typename X17, typename X18, | |||||
typename... Xn> | |||||
static constexpr auto apply( | |||||
F&& f, | |||||
X1&& x1, X2&& x2, X3&& x3, X4&& x4, X5&& x5, X6&& x6, X7&& x7, X8&& x8, X9&& x9, | |||||
X10&& x10, X11&& x11, X12&& x12, X13&& x13, X14&& x14, X15&& x15, X16&& x16, X17&& x17, X18&& x18, | |||||
Xn&&... xn) | |||||
{ | |||||
return fold_left_impl<sizeof...(xn) + 1>::apply( | |||||
f, | |||||
f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f( | |||||
std::forward<X1> (x1), | |||||
std::forward<X2> (x2)), | |||||
std::forward<X3> (x3)), | |||||
std::forward<X4> (x4)), | |||||
std::forward<X5> (x5)), | |||||
std::forward<X6> (x6)), | |||||
std::forward<X7> (x7)), | |||||
std::forward<X8> (x8)), | |||||
std::forward<X9> (x9)), | |||||
std::forward<X10>(x10)), | |||||
std::forward<X11>(x11)), | |||||
std::forward<X12>(x12)), | |||||
std::forward<X13>(x13)), | |||||
std::forward<X14>(x14)), | |||||
std::forward<X15>(x15)), | |||||
std::forward<X16>(x16)), | |||||
std::forward<X17>(x17)), | |||||
std::forward<X18>(x18)), | |||||
std::forward<Xn>(xn)... | |||||
); | |||||
} | |||||
}; | |||||
template<unsigned int n> | |||||
struct fold_left_impl<n, when<(n >= 36)>> | |||||
{ | |||||
template< | |||||
typename F, | |||||
typename X1, typename X2, typename X3, typename X4, typename X5, typename X6, typename X7, typename X8, typename X9, | |||||
typename X10, typename X11, typename X12, typename X13, typename X14, typename X15, typename X16, typename X17, typename X18, | |||||
typename X19, typename X20, typename X21, typename X22, typename X23, typename X24, typename X25, typename X26, typename X27, | |||||
typename X28, typename X29, typename X30, typename X31, typename X32, typename X33, typename X34, typename X35, typename X36, | |||||
typename... Xn> | |||||
static constexpr auto apply( | |||||
F&& f, | |||||
X1&& x1, X2&& x2, X3&& x3, X4&& x4, X5&& x5, X6&& x6, X7&& x7, X8&& x8, X9&& x9, | |||||
X10&& x10, X11&& x11, X12&& x12, X13&& x13, X14&& x14, X15&& x15, X16&& x16, X17&& x17, X18&& x18, | |||||
X19&& x19, X20&& x20, X21&& x21, X22&& x22, X23&& x23, X24&& x24, X25&& x25, X26&& x26, X27&& x27, | |||||
X28&& x28, X29&& x29, X30&& x30, X31&& x31, X32&& x32, X33&& x33, X34&& x34, X35&& x35, X36&& x36, | |||||
Xn&&... xn) | |||||
{ | |||||
return fold_left_impl<sizeof...(xn) + 1>::apply( | |||||
f, | |||||
f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f(f( | |||||
std::forward<X1> (x1), | |||||
std::forward<X2> (x2)), | |||||
std::forward<X3> (x3)), | |||||
std::forward<X4> (x4)), | |||||
std::forward<X5> (x5)), | |||||
std::forward<X6> (x6)), | |||||
std::forward<X7> (x7)), | |||||
std::forward<X8> (x8)), | |||||
std::forward<X9> (x9)), | |||||
std::forward<X10>(x10)), | |||||
std::forward<X11>(x11)), | |||||
std::forward<X12>(x12)), | |||||
std::forward<X13>(x13)), | |||||
std::forward<X14>(x14)), | |||||
std::forward<X15>(x15)), | |||||
std::forward<X16>(x16)), | |||||
std::forward<X17>(x17)), | |||||
std::forward<X18>(x18)), | |||||
std::forward<X19>(x19)), | |||||
std::forward<X20>(x20)), | |||||
std::forward<X21>(x21)), | |||||
std::forward<X22>(x22)), | |||||
std::forward<X23>(x23)), | |||||
std::forward<X24>(x24)), | |||||
std::forward<X25>(x25)), | |||||
std::forward<X26>(x26)), | |||||
std::forward<X27>(x27)), | |||||
std::forward<X28>(x28)), | |||||
std::forward<X29>(x29)), | |||||
std::forward<X30>(x30)), | |||||
std::forward<X31>(x31)), | |||||
std::forward<X32>(x32)), | |||||
std::forward<X33>(x33)), | |||||
std::forward<X34>(x34)), | |||||
std::forward<X35>(x35)), | |||||
std::forward<X36>(x36)), | |||||
std::forward<Xn>(xn)... | |||||
); | |||||
} | |||||
}; | |||||
struct fold_left_t | |||||
{ | |||||
template<typename F, typename X1, typename... Xn> | |||||
constexpr auto operator()(F&& f, X1&& x1, Xn&&... xn) const | |||||
{ return fold_left_impl<sizeof...(xn) + 1>::apply(std::forward<F>(f), std::forward<X1>(x1), std::forward<Xn>(xn)...); } | |||||
}; | |||||
} | |||||
constexpr __impl::fold_left_t fold_left { }; | |||||
} | |||||
} | |||||
} |
@@ -0,0 +1,244 @@ | |||||
#pragma once | |||||
#include <utility> | |||||
#include <cpputils/mp/misc/when.h> | |||||
namespace utl { | |||||
namespace mp { | |||||
namespace intern { | |||||
namespace __impl | |||||
{ | |||||
template <unsigned int n, typename = when<true>> | |||||
struct fold_right_impl; | |||||
template<> | |||||
struct fold_right_impl<1> | |||||
{ | |||||
template<typename F, typename X1> | |||||
static constexpr X1 apply(F&&, X1&& x1) | |||||
{ return std::forward<X1>(x1); } | |||||
}; | |||||
template<> | |||||
struct fold_right_impl<2> | |||||
{ | |||||
template<typename F, typename X1, typename X2> | |||||
static constexpr auto apply(F&& f, X1&& x1, X2&& x2) | |||||
{ | |||||
return f( | |||||
std::forward<X1>(x1), | |||||
std::forward<X2>(x2)); | |||||
} | |||||
}; | |||||
template<> | |||||
struct fold_right_impl<3> | |||||
{ | |||||
template<typename F, typename X1, typename X2, typename X3> | |||||
static constexpr auto apply(F&& f, X1&& x1, X2&& x2, X3&& x3) | |||||
{ | |||||
return f(std::forward<X1>(x1), | |||||
f(std::forward<X2>(x2), | |||||
std::forward<X3>(x3))); | |||||
} | |||||
}; | |||||
template<> | |||||
struct fold_right_impl<4> | |||||
{ | |||||
template<typename F, typename X1, typename X2, typename X3, typename X4> | |||||
static constexpr auto apply(F&& f, X1&& x1, X2&& x2, X3&& x3, X4&& x4) | |||||
{ | |||||
return f(std::forward<X1>(x1), | |||||
f(std::forward<X2>(x2), | |||||
f(std::forward<X3>(x3), | |||||
std::forward<X4>(x4)))); | |||||
} | |||||
}; | |||||
template<> | |||||
struct fold_right_impl<5> | |||||
{ | |||||
template<typename F, typename X1, typename X2, typename X3, typename X4, typename X5> | |||||
static constexpr auto apply(F&& f, X1&& x1, X2&& x2, X3&& x3, X4&& x4, X5&& x5) | |||||
{ | |||||
return f(std::forward<X1>(x1), | |||||
f(std::forward<X2>(x2), | |||||
f(std::forward<X3>(x3), | |||||
f(std::forward<X4>(x4), | |||||
std::forward<X5>(x5))))); | |||||
} | |||||
}; | |||||
template<> | |||||
struct fold_right_impl<6> | |||||
{ | |||||
template<typename F, typename X1, typename X2, typename X3, typename X4, typename X5, typename X6> | |||||
static constexpr auto apply(F&& f, X1&& x1, X2&& x2, X3&& x3, X4&& x4, X5&& x5, X6&& x6) | |||||
{ | |||||
return f(std::forward<X1>(x1), | |||||
f(std::forward<X2>(x2), | |||||
f(std::forward<X3>(x3), | |||||
f(std::forward<X4>(x4), | |||||
f(std::forward<X5>(x5), | |||||
std::forward<X6>(x6)))))); | |||||
} | |||||
}; | |||||
template<> | |||||
struct fold_right_impl<7> | |||||
{ | |||||
template<typename F, typename X1, typename X2, typename X3, typename X4, typename X5, typename X6, typename X7> | |||||
static constexpr auto apply(F&& f, X1&& x1, X2&& x2, X3&& x3, X4&& x4, X5&& x5, X6&& x6, X7&& x7) | |||||
{ | |||||
return f(std::forward<X1>(x1), | |||||
f(std::forward<X2>(x2), | |||||
f(std::forward<X3>(x3), | |||||
f(std::forward<X4>(x4), | |||||
f(std::forward<X5>(x5), | |||||
f(std::forward<X6>(x6), | |||||
std::forward<X7>(x7))))))); | |||||
} | |||||
}; | |||||
template<> | |||||
struct fold_right_impl<8> | |||||
{ | |||||
template<typename F, typename X1, typename X2, typename X3, typename X4, typename X5, typename X6, typename X7, typename X8> | |||||
static constexpr auto apply(F&& f, X1&& x1, X2&& x2, X3&& x3, X4&& x4, X5&& x5, X6&& x6, X7&& x7, X8&& x8) | |||||
{ | |||||
return f(std::forward<X1>(x1), | |||||
f(std::forward<X2>(x2), | |||||
f(std::forward<X3>(x3), | |||||
f(std::forward<X4>(x4), | |||||
f(std::forward<X5>(x5), | |||||
f(std::forward<X6>(x6), | |||||
f(std::forward<X7>(x7), | |||||
std::forward<X8>(x8)))))))); | |||||
} | |||||
}; | |||||
template<unsigned int n> | |||||
struct fold_right_impl<n, when<(n >= 9) && (n < 18)>> | |||||
{ | |||||
template<typename F, typename X1, typename X2, typename X3, typename X4, typename X5, typename X6, typename X7, typename X8, typename X9, typename... Xn> | |||||
static constexpr auto apply(F&& f, X1&& x1, X2&& x2, X3&& x3, X4&& x4, X5&& x5, X6&& x6, X7&& x7, X8&& x8, X9&& x9, Xn&&... xn) | |||||
{ | |||||
return f(std::forward<X1>(x1), | |||||
f(std::forward<X2>(x2), | |||||
f(std::forward<X3>(x3), | |||||
f(std::forward<X4>(x4), | |||||
f(std::forward<X5>(x5), | |||||
f(std::forward<X6>(x6), | |||||
f(std::forward<X7>(x7), | |||||
f(std::forward<X8>(x8), | |||||
fold_right_impl<sizeof...(xn) + 1>::apply(f, std::forward<X9>(x9), std::forward<Xn>(xn)...))))))))); | |||||
} | |||||
}; | |||||
template<unsigned int n> | |||||
struct fold_right_impl<n, when<(n >= 18) && (n < 36)>> | |||||
{ | |||||
template< | |||||
typename F, | |||||
typename X1, typename X2, typename X3, typename X4, typename X5, typename X6, typename X7, typename X8, typename X9, | |||||
typename X10, typename X11, typename X12, typename X13, typename X14, typename X15, typename X16, typename X17, typename X18, | |||||
typename... Xn> | |||||
static constexpr auto apply( | |||||
F&& f, | |||||
X1&& x1, X2&& x2, X3&& x3, X4&& x4, X5&& x5, X6&& x6, X7&& x7, X8&& x8, X9&& x9, | |||||
X10&& x10, X11&& x11, X12&& x12, X13&& x13, X14&& x14, X15&& x15, X16&& x16, X17&& x17, X18&& x18, | |||||
Xn&&... xn) | |||||
{ | |||||
return f(std::forward<X1> (x1), | |||||
f(std::forward<X2> (x2), | |||||
f(std::forward<X3> (x3), | |||||
f(std::forward<X4> (x4), | |||||
f(std::forward<X5> (x5), | |||||
f(std::forward<X6> (x6), | |||||
f(std::forward<X7> (x7), | |||||
f(std::forward<X8> (x8), | |||||
f(std::forward<X9> (x9), | |||||
f(std::forward<X10>(x10), | |||||
f(std::forward<X11>(x11), | |||||
f(std::forward<X12>(x12), | |||||
f(std::forward<X13>(x13), | |||||
f(std::forward<X14>(x14), | |||||
f(std::forward<X15>(x15), | |||||
f(std::forward<X16>(x16), | |||||
f(std::forward<X17>(x17), | |||||
fold_right_impl<sizeof...(xn) + 1>::apply(f, std::forward<X18>(x18), std::forward<Xn>(xn)...)))))))))))))))))); | |||||
} | |||||
}; | |||||
template<unsigned int n> | |||||
struct fold_right_impl<n, when<(n >= 36)>> | |||||
{ | |||||
template< | |||||
typename F, | |||||
typename X1, typename X2, typename X3, typename X4, typename X5, typename X6, typename X7, typename X8, typename X9, | |||||
typename X10, typename X11, typename X12, typename X13, typename X14, typename X15, typename X16, typename X17, typename X18, | |||||
typename X19, typename X20, typename X21, typename X22, typename X23, typename X24, typename X25, typename X26, typename X27, | |||||
typename X28, typename X29, typename X30, typename X31, typename X32, typename X33, typename X34, typename X35, typename X36, | |||||
typename... Xn> | |||||
static constexpr auto apply( | |||||
F&& f, | |||||
X1&& x1, X2&& x2, X3&& x3, X4&& x4, X5&& x5, X6&& x6, X7&& x7, X8&& x8, X9&& x9, | |||||
X10&& x10, X11&& x11, X12&& x12, X13&& x13, X14&& x14, X15&& x15, X16&& x16, X17&& x17, X18&& x18, | |||||
X19&& x19, X20&& x20, X21&& x21, X22&& x22, X23&& x23, X24&& x24, X25&& x25, X26&& x26, X27&& x27, | |||||
X28&& x28, X29&& x29, X30&& x30, X31&& x31, X32&& x32, X33&& x33, X34&& x34, X35&& x35, X36&& x36, | |||||
Xn&&... xn) | |||||
{ | |||||
return f(std::forward<X1> (x1), | |||||
f(std::forward<X2> (x2), | |||||
f(std::forward<X3> (x3), | |||||
f(std::forward<X4> (x4), | |||||
f(std::forward<X5> (x5), | |||||
f(std::forward<X6> (x6), | |||||
f(std::forward<X7> (x7), | |||||
f(std::forward<X8> (x8), | |||||
f(std::forward<X9> (x9), | |||||
f(std::forward<X10>(x10), | |||||
f(std::forward<X11>(x11), | |||||
f(std::forward<X12>(x12), | |||||
f(std::forward<X13>(x13), | |||||
f(std::forward<X14>(x14), | |||||
f(std::forward<X15>(x15), | |||||
f(std::forward<X16>(x16), | |||||
f(std::forward<X17>(x17), | |||||
f(std::forward<X18>(x18), | |||||
f(std::forward<X19>(x19), | |||||
f(std::forward<X20>(x20), | |||||
f(std::forward<X21>(x21), | |||||
f(std::forward<X22>(x22), | |||||
f(std::forward<X23>(x23), | |||||
f(std::forward<X24>(x24), | |||||
f(std::forward<X25>(x25), | |||||
f(std::forward<X26>(x26), | |||||
f(std::forward<X27>(x27), | |||||
f(std::forward<X28>(x28), | |||||
f(std::forward<X29>(x29), | |||||
f(std::forward<X30>(x30), | |||||
f(std::forward<X31>(x31), | |||||
f(std::forward<X32>(x32), | |||||
f(std::forward<X33>(x33), | |||||
f(std::forward<X34>(x34), | |||||
f(std::forward<X35>(x35), | |||||
fold_right_impl<sizeof...(xn) + 1>::apply(f, std::forward<X36>(x36), std::forward<Xn>(xn)...)))))))))))))))))))))))))))))))))))); | |||||
} | |||||
}; | |||||
struct fold_right_t | |||||
{ | |||||
template<typename F, typename X1, typename... Xn> | |||||
constexpr auto operator()(F&& f, X1&& x1, Xn&&... xn) const | |||||
{ return fold_right_impl<sizeof...(xn) + 1>::apply(std::forward<F>(f), std::forward<X1>(x1), std::forward<Xn>(xn)...); } | |||||
}; | |||||
} | |||||
constexpr __impl::fold_right_t fold_right { }; | |||||
} | |||||
} | |||||
} |
@@ -8,9 +8,9 @@ namespace intern { | |||||
template<typename C> | template<typename C> | ||||
struct has_value | struct has_value | ||||
: c_bool<!is_default<__impl::value_impl<tag_of<C>>>::value> | |||||
: c_bool_t<!is_default<::utl::mp::__impl::value_impl<tag_of<C>>>::value> | |||||
{ }; | { }; | ||||
} | } | ||||
} | } | ||||
} | |||||
} |
@@ -0,0 +1,61 @@ | |||||
#pragma once | |||||
#include <cpputils/mp/operations/hash.h> | |||||
#include <cpputils/mp/operations/compare/equal.h> | |||||
namespace utl { | |||||
namespace mp { | |||||
namespace intern { | |||||
namespace __impl | |||||
{ | |||||
template<typename H, size_t... I> | |||||
struct bucket { }; | |||||
template<typename... Buckets> | |||||
struct hash_table | |||||
: Buckets... | |||||
{ }; | |||||
/* find indices */ | |||||
template<typename Hash, size_t... I> | |||||
std::index_sequence<I...> find_indices_impl(const bucket<Hash, I...>&); | |||||
template<typename Hash> | |||||
std::index_sequence<> find_indices_impl(...); | |||||
/* find index */ | |||||
template<template<size_t> class KeyAtIndex, typename Key> | |||||
struct find_pred | |||||
{ | |||||
template<typename Index> | |||||
auto operator()(const Index&) const -> | |||||
decltype(equal(std::declval<KeyAtIndex<Index::value>>(), std::declval<Key>())); | |||||
}; | |||||
template<typename Indices, typename Key, template<size_t> class KeyAtIndex> | |||||
struct find_index_impl | |||||
{ using type = decltype(find_if(Indices { }, find_pred<KeyAtIndex, Key> { })); }; | |||||
} | |||||
template<typename Map, typename Key> | |||||
struct find_indices | |||||
{ | |||||
using hash = typename decltype(hash(std::declval<Key>()))::type; | |||||
using type = decltype(__impl::find_indices_impl<hash>(std::declval<Map>())); | |||||
}; | |||||
template<template<size_t> class KeyAtIndex, size_t N, typename Indices = std::make_index_sequence<N>> | |||||
struct make_hash_table; | |||||
template<template<size_t> class KeyAtIndex, size_t N, size_t... I> | |||||
struct make_hash_table<KeyAtIndex, N, std::index_sequence<I...>> | |||||
{ | |||||
using type = __impl::hash_table< | |||||
__impl::bucket<typename decltype(hash(std::declval<KeyAtIndex<I>>()))::type, I>... | |||||
>; | |||||
}; | |||||
} | |||||
} | |||||
} |
@@ -2,7 +2,7 @@ | |||||
#include <utility> | #include <utility> | ||||
#include <cpputils/mp/core/conditionals.h> | #include <cpputils/mp/core/conditionals.h> | ||||
#include <cpputils/mp/util/tag_of.h> | |||||
#include <cpputils/mp/misc/tag_of.h> | |||||
#include <cpputils/mp/operations/compare/equal.h> | #include <cpputils/mp/operations/compare/equal.h> | ||||
#include <cpputils/mp/operations/compare/not_equal.h> | #include <cpputils/mp/operations/compare/not_equal.h> | ||||
@@ -2,7 +2,7 @@ | |||||
#include <utility> | #include <utility> | ||||
#include <cpputils/mp/core/conditionals.h> | #include <cpputils/mp/core/conditionals.h> | ||||
#include <cpputils/mp/util/tag_of.h> | |||||
#include <cpputils/mp/misc/tag_of.h> | |||||
#include <cpputils/mp/operations/compare/less.h> | #include <cpputils/mp/operations/compare/less.h> | ||||
#include <cpputils/mp/operations/compare/less_equal.h> | #include <cpputils/mp/operations/compare/less_equal.h> | ||||
#include <cpputils/mp/operations/compare/greater.h> | #include <cpputils/mp/operations/compare/greater.h> | ||||
@@ -0,0 +1,8 @@ | |||||
#pragma once | |||||
#include <cpputils/mp/misc/default.h> | |||||
#include <cpputils/mp/misc/is_a.h> | |||||
#include <cpputils/mp/misc/make.h> | |||||
#include <cpputils/mp/misc/tag_of.h> | |||||
#include <cpputils/mp/misc/when.h> | |||||
#include <cpputils/mp/misc/to.h> |
@@ -20,12 +20,12 @@ namespace mp { | |||||
template<typename T, typename> | template<typename T, typename> | ||||
struct is_default_impl : | struct is_default_impl : | ||||
public c_false | |||||
public c_false_t | |||||
{ }; | { }; | ||||
template<typename T> | template<typename T> | ||||
struct is_default_impl<T, decltype((void)static_cast<default_>(std::declval<T>()))> : | struct is_default_impl<T, decltype((void)static_cast<default_>(std::declval<T>()))> : | ||||
public c_true | |||||
public c_true_t | |||||
{ }; | { }; | ||||
} | } | ||||
@@ -1,7 +1,7 @@ | |||||
#pragma once | #pragma once | ||||
#include <cpputils/mp/util/when.h> | |||||
#include <cpputils/mp/util/tag_of.h> | |||||
#include <cpputils/mp/misc/when.h> | |||||
#include <cpputils/mp/misc/tag_of.h> | |||||
namespace utl { | namespace utl { | ||||
namespace mp { | namespace mp { |
@@ -2,8 +2,8 @@ | |||||
#pragma once | #pragma once | ||||
#include <utility> | #include <utility> | ||||
#include <cpputils/mp/util/when.h> | |||||
#include <cpputils/mp/util/default.h> | |||||
#include <cpputils/mp/misc/when.h> | |||||
#include <cpputils/mp/misc/default.h> | |||||
namespace utl { | namespace utl { | ||||
namespace mp { | namespace mp { |
@@ -1,7 +1,7 @@ | |||||
#pragma once | #pragma once | ||||
#include <cpputils/mp/core/modifier.h> | #include <cpputils/mp/core/modifier.h> | ||||
#include <cpputils/mp/util/when.h> | |||||
#include <cpputils/mp/misc/when.h> | |||||
namespace utl { | namespace utl { | ||||
namespace mp { | namespace mp { |
@@ -1,7 +1,7 @@ | |||||
#pragma once | #pragma once | ||||
#include <cpputils/mp/util/when.h> | |||||
#include <cpputils/mp/util/tag_of.h> | |||||
#include <cpputils/mp/misc/when.h> | |||||
#include <cpputils/mp/misc/tag_of.h> | |||||
#include <cpputils/mp/core/conditionals.h> | #include <cpputils/mp/core/conditionals.h> | ||||
namespace utl { | namespace utl { |
@@ -24,7 +24,7 @@ namespace mp { | |||||
{ | { | ||||
template<typename...> | template<typename...> | ||||
struct wrong_impl : | struct wrong_impl : | ||||
public c_false | |||||
public c_false_t | |||||
{ }; | { }; | ||||
} | } | ||||
@@ -1,6 +1,15 @@ | |||||
#pragma once | #pragma once | ||||
#include <cpputils/mp/operations/at.h> | |||||
#include <cpputils/mp/operations/compare.h> | |||||
#include <cpputils/mp/operations/eval_if.h> | |||||
#include <cpputils/mp/operations/eval.h> | |||||
#include <cpputils/mp/operations/first.h> | #include <cpputils/mp/operations/first.h> | ||||
#include <cpputils/mp/operations/hash.h> | |||||
#include <cpputils/mp/operations/if.h> | |||||
#include <cpputils/mp/operations/length.h> | |||||
#include <cpputils/mp/operations/logical.h> | |||||
#include <cpputils/mp/operations/second.h> | #include <cpputils/mp/operations/second.h> | ||||
#include <cpputils/mp/operations/compare.h> | |||||
#include <cpputils/mp/operations/logical.h> | |||||
#include <cpputils/mp/operations/transform.h> | |||||
#include <cpputils/mp/operations/unpack.h> | |||||
#include <cpputils/mp/operations/value.h> |
@@ -0,0 +1,52 @@ | |||||
#pragma once | |||||
#include <utility> | |||||
#include <cpputils/mp/core/const.h> | |||||
#include <cpputils/mp/misc/when.h> | |||||
#include <cpputils/mp/misc/tag_of.h> | |||||
#include <cpputils/mp/misc/default.h> | |||||
namespace utl { | |||||
namespace mp { | |||||
namespace __impl | |||||
{ | |||||
struct at_t | |||||
{ | |||||
template<typename Xs, typename N> | |||||
constexpr auto operator()(Xs&& xs, const N& n) const; | |||||
}; | |||||
} | |||||
constexpr __impl::at_t at { }; | |||||
template<size_t N, typename Xs> | |||||
constexpr auto at_c(Xs&& xs) | |||||
{ return at(std::forward<Xs>(xs), c_size_t<N> { }); } | |||||
namespace __impl | |||||
{ | |||||
template <typename T, typename = void> | |||||
struct at_impl | |||||
: at_impl<T, when<true>> | |||||
{ }; | |||||
template <typename T, bool condition> | |||||
struct at_impl<T, when<condition>> | |||||
: default_ | |||||
{ | |||||
template <typename ...Args> | |||||
static constexpr auto apply(Args&& ...) = delete; | |||||
}; | |||||
template<typename Xs, typename N> | |||||
constexpr auto at_t::operator()(Xs&& xs, const N& n) const | |||||
{ | |||||
using tag_type = tag_of<Xs>; | |||||
using at_impl_type = at_impl<tag_type>; | |||||
return at_impl_type::apply(std::forward<Xs>(xs), n); | |||||
} | |||||
} | |||||
} | |||||
} |
@@ -1,9 +1,9 @@ | |||||
#pragma once | #pragma once | ||||
#include <cpputils/mp/core/const.h> | #include <cpputils/mp/core/const.h> | ||||
#include <cpputils/mp/util/when.h> | |||||
#include <cpputils/mp/util/tag_of.h> | |||||
#include <cpputils/mp/util/default.h> | |||||
#include <cpputils/mp/misc/when.h> | |||||
#include <cpputils/mp/misc/tag_of.h> | |||||
#include <cpputils/mp/misc/default.h> | |||||
#include <cpputils/mp/intern/has_value.h> | #include <cpputils/mp/intern/has_value.h> | ||||
#include <cpputils/mp/intern/comparable_equal.h> | #include <cpputils/mp/intern/comparable_equal.h> | ||||
#include <cpputils/mp/operations/if.h> | #include <cpputils/mp/operations/if.h> | ||||
@@ -36,7 +36,7 @@ namespace mp { | |||||
{ | { | ||||
template <typename ...Args> | template <typename ...Args> | ||||
static constexpr auto apply(Args&& ...) | static constexpr auto apply(Args&& ...) | ||||
{ return c_false { }; } | |||||
{ return c_false; } | |||||
}; | }; | ||||
template <typename T, typename U> | template <typename T, typename U> | ||||
@@ -55,7 +55,7 @@ namespace mp { | |||||
{ | { | ||||
constexpr auto eq = equal(value<X>(), value<Y>()); | constexpr auto eq = equal(value<X>(), value<Y>()); | ||||
constexpr bool truth_value = if_ (eq, true, false); | constexpr bool truth_value = if_ (eq, true, false); | ||||
return c_bool<truth_value> { }; | |||||
return c_bool_t<truth_value> { }; | |||||
} | } | ||||
}; | }; | ||||
@@ -1,9 +1,9 @@ | |||||
#pragma once | #pragma once | ||||
#include <cpputils/mp/core/const.h> | #include <cpputils/mp/core/const.h> | ||||
#include <cpputils/mp/util/when.h> | |||||
#include <cpputils/mp/util/tag_of.h> | |||||
#include <cpputils/mp/util/default.h> | |||||
#include <cpputils/mp/misc/when.h> | |||||
#include <cpputils/mp/misc/tag_of.h> | |||||
#include <cpputils/mp/misc/default.h> | |||||
#include <cpputils/mp/operations/logical/not.h> | #include <cpputils/mp/operations/logical/not.h> | ||||
#include <cpputils/mp/operations/compare/less.h> | #include <cpputils/mp/operations/compare/less.h> | ||||
@@ -1,9 +1,9 @@ | |||||
#pragma once | #pragma once | ||||
#include <cpputils/mp/core/const.h> | #include <cpputils/mp/core/const.h> | ||||
#include <cpputils/mp/util/when.h> | |||||
#include <cpputils/mp/util/tag_of.h> | |||||
#include <cpputils/mp/util/default.h> | |||||
#include <cpputils/mp/misc/when.h> | |||||
#include <cpputils/mp/misc/tag_of.h> | |||||
#include <cpputils/mp/misc/default.h> | |||||
#include <cpputils/mp/operations/logical/not.h> | #include <cpputils/mp/operations/logical/not.h> | ||||
#include <cpputils/mp/operations/compare/less.h> | #include <cpputils/mp/operations/compare/less.h> | ||||
@@ -1,9 +1,9 @@ | |||||
#pragma once | #pragma once | ||||
#include <cpputils/mp/core/const.h> | #include <cpputils/mp/core/const.h> | ||||
#include <cpputils/mp/util/when.h> | |||||
#include <cpputils/mp/util/tag_of.h> | |||||
#include <cpputils/mp/util/default.h> | |||||
#include <cpputils/mp/misc/when.h> | |||||
#include <cpputils/mp/misc/tag_of.h> | |||||
#include <cpputils/mp/misc/default.h> | |||||
#include <cpputils/mp/intern/has_value.h> | #include <cpputils/mp/intern/has_value.h> | ||||
#include <cpputils/mp/intern/comparable_less.h> | #include <cpputils/mp/intern/comparable_less.h> | ||||
#include <cpputils/mp/operations/if.h> | #include <cpputils/mp/operations/if.h> | ||||
@@ -36,7 +36,7 @@ namespace mp { | |||||
{ | { | ||||
template <typename ...Args> | template <typename ...Args> | ||||
static constexpr auto apply(Args&& ...) | static constexpr auto apply(Args&& ...) | ||||
{ return c_false { }; } | |||||
{ return c_false; } | |||||
}; | }; | ||||
template <typename T, typename U> | template <typename T, typename U> | ||||
@@ -55,7 +55,7 @@ namespace mp { | |||||
{ | { | ||||
constexpr auto eq = less(value<X>(), value<Y>()); | constexpr auto eq = less(value<X>(), value<Y>()); | ||||
constexpr bool truth_value = if_ (eq, true, false); | constexpr bool truth_value = if_ (eq, true, false); | ||||
return c_bool<truth_value> { }; | |||||
return c_bool_t<truth_value> { }; | |||||
} | } | ||||
}; | }; | ||||
@@ -1,9 +1,9 @@ | |||||
#pragma once | #pragma once | ||||
#include <cpputils/mp/core/const.h> | #include <cpputils/mp/core/const.h> | ||||
#include <cpputils/mp/util/when.h> | |||||
#include <cpputils/mp/util/tag_of.h> | |||||
#include <cpputils/mp/util/default.h> | |||||
#include <cpputils/mp/misc/when.h> | |||||
#include <cpputils/mp/misc/tag_of.h> | |||||
#include <cpputils/mp/misc/default.h> | |||||
#include <cpputils/mp/operations/logical/not.h> | #include <cpputils/mp/operations/logical/not.h> | ||||
#include <cpputils/mp/operations/compare/less.h> | #include <cpputils/mp/operations/compare/less.h> | ||||
@@ -1,9 +1,9 @@ | |||||
#pragma once | #pragma once | ||||
#include <cpputils/mp/core/const.h> | #include <cpputils/mp/core/const.h> | ||||
#include <cpputils/mp/util/when.h> | |||||
#include <cpputils/mp/util/tag_of.h> | |||||
#include <cpputils/mp/util/default.h> | |||||
#include <cpputils/mp/misc/when.h> | |||||
#include <cpputils/mp/misc/tag_of.h> | |||||
#include <cpputils/mp/misc/default.h> | |||||
#include <cpputils/mp/operations/logical/not.h> | #include <cpputils/mp/operations/logical/not.h> | ||||
#include <cpputils/mp/operations/compare/not_equal.h> | #include <cpputils/mp/operations/compare/not_equal.h> | ||||
@@ -1,9 +1,9 @@ | |||||
#pragma once | #pragma once | ||||
#include <utility> | #include <utility> | ||||
#include <cpputils/mp/util/when.h> | |||||
#include <cpputils/mp/util/tag_of.h> | |||||
#include <cpputils/mp/util/default.h> | |||||
#include <cpputils/mp/misc/when.h> | |||||
#include <cpputils/mp/misc/tag_of.h> | |||||
#include <cpputils/mp/misc/default.h> | |||||
namespace utl { | namespace utl { | ||||
namespace mp { | namespace mp { | ||||
@@ -1,8 +1,8 @@ | |||||
#pragma once | #pragma once | ||||
#include <cpputils/mp/util/when.h> | |||||
#include <cpputils/mp/util/tag_of.h> | |||||
#include <cpputils/mp/util/default.h> | |||||
#include <cpputils/mp/misc/when.h> | |||||
#include <cpputils/mp/misc/tag_of.h> | |||||
#include <cpputils/mp/misc/default.h> | |||||
#include <cpputils/mp/intern/has_value.h> | #include <cpputils/mp/intern/has_value.h> | ||||
#include <cpputils/mp/operations/if.fwd.h> | #include <cpputils/mp/operations/if.fwd.h> | ||||
#include <cpputils/mp/operations/eval.h> | #include <cpputils/mp/operations/eval.h> | ||||
@@ -51,11 +51,11 @@ namespace mp { | |||||
struct eval_if_impl<T, when<intern::has_value<T>::value>> | struct eval_if_impl<T, when<intern::has_value<T>::value>> | ||||
{ | { | ||||
template<typename Then, typename Else> | template<typename Then, typename Else> | ||||
static constexpr auto eval_if_helper(c_true, Then&& t, Else&& e) | |||||
static constexpr auto eval_if_helper(c_true_t, Then&& t, Else&& e) | |||||
{ return eval(std::forward<Then>(t)); } | { return eval(std::forward<Then>(t)); } | ||||
template<typename Then, typename Else> | template<typename Then, typename Else> | ||||
static constexpr auto eval_if_helper(c_false, Then&& t, Else&& e) | |||||
static constexpr auto eval_if_helper(c_false_t, Then&& t, Else&& e) | |||||
{ return eval(std::forward<Else>(e)); } | { return eval(std::forward<Else>(e)); } | ||||
template <typename Cond, typename Then, typename Else> | template <typename Cond, typename Then, typename Else> | ||||
@@ -63,7 +63,7 @@ namespace mp { | |||||
{ | { | ||||
constexpr auto cond = value<Cond>(); | constexpr auto cond = value<Cond>(); | ||||
constexpr bool truth_value = if_(cond, true, false); | constexpr bool truth_value = if_(cond, true, false); | ||||
return eval_if_helper(c_bool<truth_value> { }, std::forward<Then>(t), std::forward<Else>(e)); | |||||
return eval_if_helper(c_bool_t<truth_value> { }, std::forward<Then>(t), std::forward<Else>(e)); | |||||
} | } | ||||
}; | }; | ||||
@@ -1,8 +1,8 @@ | |||||
#pragma once | #pragma once | ||||
#include <cpputils/mp/util/when.h> | |||||
#include <cpputils/mp/util/tag_of.h> | |||||
#include <cpputils/mp/util/default.h> | |||||
#include <cpputils/mp/misc/when.h> | |||||
#include <cpputils/mp/misc/tag_of.h> | |||||
#include <cpputils/mp/misc/default.h> | |||||
namespace utl { | namespace utl { | ||||
namespace mp { | namespace mp { | ||||
@@ -0,0 +1,28 @@ | |||||
#pragma once | |||||
#include <cpputils/mp/misc/when.h> | |||||
#include <cpputils/mp/misc/tag_of.h> | |||||
#include <cpputils/mp/misc/default.h> | |||||
#include <cpputils/mp/core/const.h> | |||||
#include <cpputils/mp/core/modifier.h> | |||||
#include <cpputils/mp/container/type.h> | |||||
namespace utl { | |||||
namespace mp { | |||||
namespace __impl /* forward declaration */ | |||||
{ | |||||
struct hash_t | |||||
{ | |||||
template<typename X> | |||||
constexpr auto operator()(const X& x) const; | |||||
}; | |||||
template <typename T, typename = void> | |||||
struct hash_impl; | |||||
} | |||||
constexpr __impl::hash_t hash { }; | |||||
} | |||||
} |
@@ -0,0 +1,104 @@ | |||||
#pragma once | |||||
#include <cpputils/mp/misc/when.h> | |||||
#include <cpputils/mp/misc/tag_of.h> | |||||
#include <cpputils/mp/misc/default.h> | |||||
#include <cpputils/mp/core/const.h> | |||||
#include <cpputils/mp/core/modifier.h> | |||||
#include <cpputils/mp/core/conditionals.h> | |||||
#include <cpputils/mp/container/type.h> | |||||
#include <cpputils/mp/operations/hash.fwd.h> | |||||
namespace utl { | |||||
namespace mp { | |||||
namespace __impl /* implementation */ | |||||
{ | |||||
template <typename T, typename = void> | |||||
struct hash_integral_helper; | |||||
template <typename Member, typename T> | |||||
struct hash_integral_helper<Member T::*> | |||||
{ | |||||
template <typename X> | |||||
static constexpr auto apply(X const&) | |||||
{ return type_c<integral_constant<Member T::*, X::value>>; } | |||||
}; | |||||
template <typename T> | |||||
struct hash_integral_helper<T, enable_if<is_signed<T>>> | |||||
{ | |||||
template <typename X> | |||||
static constexpr auto apply(X const&) | |||||
{ | |||||
constexpr signed long long x = X::value; | |||||
return type_c<integral_constant<signed long long, x>>; | |||||
} | |||||
}; | |||||
template <typename T> | |||||
struct hash_integral_helper<T, enable_if<is_unsigned<T>>> | |||||
{ | |||||
template <typename X> | |||||
static constexpr auto apply(X const&) | |||||
{ | |||||
constexpr unsigned long long x = X::value; | |||||
return type_c<integral_constant<unsigned long long, x>>; | |||||
} | |||||
}; | |||||
template <> | |||||
struct hash_integral_helper<bool> | |||||
{ | |||||
template <typename X> | |||||
static constexpr auto apply(X const&) | |||||
{ return type_c<c_bool_t<X::value>>; } | |||||
}; | |||||
template <> | |||||
struct hash_integral_helper<char> | |||||
{ | |||||
template <typename X> | |||||
static constexpr auto apply(X const&) | |||||
{ | |||||
using T = if_c<is_signed<char>::value, signed long long, unsigned long long>; | |||||
constexpr T x = X::value; | |||||
return type_c<integral_constant<T, x>>; | |||||
} | |||||
}; | |||||
template <typename T, typename> | |||||
struct hash_impl | |||||
: hash_impl<T, when<true>> | |||||
{ }; | |||||
template <typename Tag, bool condition> | |||||
struct hash_impl<Tag, when<condition>> | |||||
: default_ | |||||
{ | |||||
template <typename X> | |||||
static constexpr auto apply(X const&) = delete; | |||||
}; | |||||
template <typename T> | |||||
struct hash_impl<tag_integral_constant<T>, when<true>> | |||||
{ | |||||
template<typename X> | |||||
static constexpr auto apply(const X& x) | |||||
{ | |||||
using type = remove_cv<decltype(X::value)>; | |||||
return hash_integral_helper<type>::apply(x); | |||||
} | |||||
}; | |||||
template<typename X> | |||||
constexpr auto hash_t::operator()(const X& x) const | |||||
{ | |||||
using tag_type = tag_of<X>; | |||||
using hash_impl_type = hash_impl<tag_type>; | |||||
return hash_impl_type::apply(x); | |||||
} | |||||
} | |||||
} | |||||
} |
@@ -2,9 +2,9 @@ | |||||
#include <cpputils/mp/operations/if.fwd.h> | #include <cpputils/mp/operations/if.fwd.h> | ||||
#include <cpputils/mp/util/when.h> | |||||
#include <cpputils/mp/util/tag_of.h> | |||||
#include <cpputils/mp/util/default.h> | |||||
#include <cpputils/mp/misc/when.h> | |||||
#include <cpputils/mp/misc/tag_of.h> | |||||
#include <cpputils/mp/misc/default.h> | |||||
#include <cpputils/mp/operations/eval_if.h> | #include <cpputils/mp/operations/eval_if.h> | ||||
namespace utl { | namespace utl { | ||||
@@ -0,0 +1,56 @@ | |||||
#pragma once | |||||
#include <cpputils/mp/core/const.h> | |||||
#include <cpputils/mp/misc/when.h> | |||||
#include <cpputils/mp/misc/tag_of.h> | |||||
#include <cpputils/mp/misc/default.h> | |||||
#include <cpputils/mp/operations/unpack.fwd.h> | |||||
namespace utl { | |||||
namespace mp { | |||||
namespace __impl | |||||
{ | |||||
struct length_t | |||||
{ | |||||
template<typename Xs> | |||||
constexpr auto operator()(const Xs& xs) const; | |||||
}; | |||||
} | |||||
constexpr __impl::length_t length { }; | |||||
namespace __impl | |||||
{ | |||||
struct length_argn | |||||
{ | |||||
template<typename... Xn> | |||||
constexpr c_size_t<sizeof...(Xn)> operator()(const Xn& ...) const | |||||
{ return { }; } | |||||
}; | |||||
template <typename T, typename = void> | |||||
struct length_impl | |||||
: length_impl<T, when<true>> | |||||
{ }; | |||||
template<typename T, bool condition> | |||||
struct length_impl<T, when<condition>> | |||||
: default_ | |||||
{ | |||||
template<typename Xs> | |||||
static constexpr auto apply(const Xs& xs) | |||||
{ return unpack(xs, length_argn { }); } | |||||
}; | |||||
template<typename Xs> | |||||
constexpr auto length_t::operator()(const Xs& xs) const | |||||
{ | |||||
using tag_type = tag_of<Xs>; | |||||
using length_impl_type = length_impl<tag_type>; | |||||
return length_impl_type::apply(xs); | |||||
} | |||||
} | |||||
} | |||||
} |
@@ -1,10 +1,11 @@ | |||||
#pragma once | #pragma once | ||||
#include <cpputils/mp/core/const.h> | #include <cpputils/mp/core/const.h> | ||||
#include <cpputils/mp/util/when.h> | |||||
#include <cpputils/mp/util/tag_of.h> | |||||
#include <cpputils/mp/util/default.h> | |||||
#include <cpputils/mp/misc/when.h> | |||||
#include <cpputils/mp/misc/tag_of.h> | |||||
#include <cpputils/mp/misc/default.h> | |||||
#include <cpputils/mp/operations/if.h> | #include <cpputils/mp/operations/if.h> | ||||
#include <cpputils/mp/intern/fold_left.h> | |||||
namespace utl { | namespace utl { | ||||
namespace mp { | namespace mp { | ||||
@@ -46,17 +47,16 @@ namespace mp { | |||||
using and_impl_type = and_impl<tag_type>; | using and_impl_type = and_impl<tag_type>; | ||||
return and_impl_type::apply(std::forward<X>(x), std::forward<Y>(y)); | return and_impl_type::apply(std::forward<X>(x), std::forward<Y>(y)); | ||||
}; | }; | ||||
/* TODO | |||||
template <typename X, typename ...Y> | template <typename X, typename ...Y> | ||||
constexpr auto and_t::operator()(X&& x, Y&& ...y) const | constexpr auto and_t::operator()(X&& x, Y&& ...y) const | ||||
{ | { | ||||
return detail::variadic::foldl1( | |||||
return intern::fold_left( | |||||
*this, | *this, | ||||
static_cast<X&&>(x), | static_cast<X&&>(x), | ||||
static_cast<Y&&>(y)... | static_cast<Y&&>(y)... | ||||
); | ); | ||||
} | } | ||||
*/ | |||||
} | } | ||||
} | } |
@@ -1,9 +1,9 @@ | |||||
#pragma once | #pragma once | ||||
#include <cpputils/mp/core/const.h> | #include <cpputils/mp/core/const.h> | ||||
#include <cpputils/mp/util/when.h> | |||||
#include <cpputils/mp/util/tag_of.h> | |||||
#include <cpputils/mp/util/default.h> | |||||
#include <cpputils/mp/misc/when.h> | |||||
#include <cpputils/mp/misc/tag_of.h> | |||||
#include <cpputils/mp/misc/default.h> | |||||
namespace utl { | namespace utl { | ||||
namespace mp { | namespace mp { | ||||
@@ -1,10 +1,11 @@ | |||||
#pragma once | #pragma once | ||||
#include <cpputils/mp/core/const.h> | #include <cpputils/mp/core/const.h> | ||||
#include <cpputils/mp/util/when.h> | |||||
#include <cpputils/mp/util/tag_of.h> | |||||
#include <cpputils/mp/util/default.h> | |||||
#include <cpputils/mp/misc/when.h> | |||||
#include <cpputils/mp/misc/tag_of.h> | |||||
#include <cpputils/mp/misc/default.h> | |||||
#include <cpputils/mp/operations/if.h> | #include <cpputils/mp/operations/if.h> | ||||
#include <cpputils/mp/intern/fold_left.h> | |||||
namespace utl { | namespace utl { | ||||
namespace mp { | namespace mp { | ||||
@@ -46,17 +47,16 @@ namespace mp { | |||||
using or_impl_type = or_impl<tag_type>; | using or_impl_type = or_impl<tag_type>; | ||||
return or_impl_type::apply(std::forward<X>(x), std::forward<Y>(y)); | return or_impl_type::apply(std::forward<X>(x), std::forward<Y>(y)); | ||||
}; | }; | ||||
/* TODO | |||||
template <typename X, typename ...Y> | template <typename X, typename ...Y> | ||||
constexpr auto or_t::operator()(X&& x, Y&& ...y) const | constexpr auto or_t::operator()(X&& x, Y&& ...y) const | ||||
{ | { | ||||
return detail::variadic::foldl1( | |||||
return intern::fold_left( | |||||
*this, | *this, | ||||
static_cast<X&&>(x), | static_cast<X&&>(x), | ||||
static_cast<Y&&>(y)... | static_cast<Y&&>(y)... | ||||
); | ); | ||||
} | } | ||||
*/ | |||||
} | } | ||||
} | } |
@@ -1,8 +1,8 @@ | |||||
#pragma once | #pragma once | ||||
#include <cpputils/mp/util/when.h> | |||||
#include <cpputils/mp/util/tag_of.h> | |||||
#include <cpputils/mp/util/default.h> | |||||
#include <cpputils/mp/misc/when.h> | |||||
#include <cpputils/mp/misc/tag_of.h> | |||||
#include <cpputils/mp/misc/default.h> | |||||
namespace utl { | namespace utl { | ||||
namespace mp { | namespace mp { | ||||
@@ -0,0 +1,68 @@ | |||||
#pragma once | |||||
#include <cpputils/mp/misc/when.h> | |||||
#include <cpputils/mp/misc/make.h> | |||||
#include <cpputils/mp/misc/tag_of.h> | |||||
#include <cpputils/mp/misc/default.h> | |||||
#include <cpputils/mp/operations/unpack.h> | |||||
namespace utl { | |||||
namespace mp { | |||||
namespace __impl | |||||
{ | |||||
struct transform_t | |||||
{ | |||||
template<typename Xs, typename F> | |||||
constexpr auto operator()(Xs&& xs, F&& f) const; | |||||
}; | |||||
} | |||||
constexpr __impl::transform_t transform { }; | |||||
namespace __impl | |||||
{ | |||||
template<typename Xs, typename = void> | |||||
struct transform_impl | |||||
: transform_impl<Xs, when<true>> | |||||
{ }; | |||||
template<typename T, bool condition> | |||||
struct transform_impl<T, when<condition>> | |||||
: default_ | |||||
{ | |||||
template<typename Xs, typename F> | |||||
static constexpr auto apply(Xs&& xs, F&& f) = delete; | |||||
}; | |||||
template<typename T> | |||||
struct transform_impl<T, when<!is_default<unpack_impl<tag_of<T>>>::value>> | |||||
{ | |||||
using tag_type = tag_of<T>; | |||||
template<typename F> | |||||
struct transformer | |||||
{ | |||||
F f; | |||||
template<typename... Xn> | |||||
constexpr auto operator()(Xn&&... xn) const | |||||
{ return make<tag_type>((*f)(std::forward<Xn>(xn))...); } | |||||
}; | |||||
template<typename Xs, typename F> | |||||
static constexpr auto apply(Xs&& xs, F&& f) | |||||
{ return unpack(std::forward<Xs>(xs), transformer<decltype(&f)> { &f }); } | |||||
}; | |||||
template<typename Xs, typename F> | |||||
constexpr auto transform_t::operator()(Xs&& xs, F&& f) const | |||||
{ | |||||
using tag_type = tag_of<Xs>; | |||||
using transform_impl_type = transform_impl<tag_type>; | |||||
return transform_impl_type::apply(std::forward<Xs>(xs), std::forward<F>(f)); | |||||
} | |||||
} | |||||
} | |||||
} |
@@ -0,0 +1,18 @@ | |||||
#pragma once | |||||
namespace utl { | |||||
namespace mp { | |||||
namespace __impl | |||||
{ | |||||
struct unpack_t | |||||
{ | |||||
template<typename Xs, typename F> | |||||
constexpr auto operator()(Xs&& xs, F&& f) const; | |||||
}; | |||||
} | |||||
constexpr __impl::unpack_t unpack { }; | |||||
} | |||||
} |
@@ -0,0 +1,61 @@ | |||||
#pragma once | |||||
#include <utility> | |||||
#include <cpputils/mp/misc/tag_of.h> | |||||
#include <cpputils/mp/misc/default.h> | |||||
#include <cpputils/mp/operations/at.h> | |||||
#include <cpputils/mp/operations/length.h> | |||||
#include <cpputils/mp/operations/unpack.fwd.h> | |||||
namespace utl { | |||||
namespace mp { | |||||
namespace __impl | |||||
{ | |||||
template<typename T, typename = void> | |||||
struct unpack_impl | |||||
: unpack_impl<T, when<true>> | |||||
{ }; | |||||
template<typename T> | |||||
struct unpack_impl<T, when< | |||||
!is_default<length_impl<tag_of<T>>>::value && | |||||
!is_default<at_impl <tag_of<T>>>::value>> | |||||
{ | |||||
template<typename Xs, typename F, size_t... I> | |||||
static constexpr auto unpack_helper(Xs&& xs, F&& f, std::index_sequence<I...>) | |||||
{ return std::forward<F>(f)(at_c<I>(std::forward<Xs>(xs))...); } | |||||
template<typename Xs, typename F> | |||||
static constexpr auto apply(Xs&& xs, F&& f) | |||||
{ | |||||
constexpr size_t N = decltype(length(xs))::value; | |||||
return unpack_helper(std::forward<Xs>(xs), std::forward<F>(f), std::make_index_sequence<N> { }); | |||||
} | |||||
}; | |||||
template<typename T, size_t N> | |||||
struct unpack_impl<T[N]> | |||||
{ | |||||
template<typename Xs, typename F, size_t... I> | |||||
static constexpr auto unpack_helper(Xs&& xs, F&& f, std::index_sequence<I...>) | |||||
{ return std::forward<F>(f)(std::forward<Xs>(xs)[I]...); } | |||||
template<typename Xs, typename F> | |||||
static constexpr auto apply(Xs&& xs, F&& f) | |||||
{ return unpack_helper(std::forward<Xs>(xs), std::forward<F>(f), std::make_index_sequence<N> { }); } | |||||
}; | |||||
// TODO: Pair, Struct | |||||
template<typename Xs, typename F> | |||||
constexpr auto unpack_t::operator()(Xs&& xs, F&& f) const | |||||
{ | |||||
using tag_type = tag_of<Xs>; | |||||
using unpack_impl_type = unpack_impl<tag_type>; | |||||
return unpack_impl_type::apply(std::forward<Xs>(xs), std::forward<F>(f)); | |||||
} | |||||
} | |||||
} | |||||
} |
@@ -1,8 +1,8 @@ | |||||
#pragma once | #pragma once | ||||
#include <cpputils/mp/util/when.h> | |||||
#include <cpputils/mp/util/tag_of.h> | |||||
#include <cpputils/mp/util/default.h> | |||||
#include <cpputils/mp/misc/when.h> | |||||
#include <cpputils/mp/misc/tag_of.h> | |||||
#include <cpputils/mp/misc/default.h> | |||||
namespace utl { | namespace utl { | ||||
namespace mp { | namespace mp { | ||||
@@ -42,7 +42,7 @@ namespace mp { | |||||
}; | }; | ||||
template <typename T> | template <typename T> | ||||
struct value_impl<tag_const<T>> | |||||
struct value_impl<tag_integral_constant<T>> | |||||
{ | { | ||||
template <typename C> | template <typename C> | ||||
static constexpr auto apply() | static constexpr auto apply() | ||||
@@ -1,8 +0,0 @@ | |||||
#pragma once | |||||
#include <cpputils/mp/util/default.h> | |||||
#include <cpputils/mp/util/is_a.h> | |||||
#include <cpputils/mp/util/make.h> | |||||
#include <cpputils/mp/util/tag_of.h> | |||||
#include <cpputils/mp/util/when.h> | |||||
#include <cpputils/mp/util/to.h> |
@@ -0,0 +1,41 @@ | |||||
#include <cpputils/mp/core/const.h> | |||||
#include <cpputils/mp/container/basic_tuple.h> | |||||
using namespace ::utl::mp; | |||||
namespace test_mp_container_basic_tuple | |||||
{ | |||||
struct op_unpack | |||||
{ | |||||
constexpr auto operator()(const c_bool_t<false>&, const c_size_t<5>&) | |||||
{ return true; } | |||||
}; | |||||
template<typename T> | |||||
struct Wrapper { }; | |||||
struct op_transform | |||||
{ | |||||
template<typename T> | |||||
constexpr auto operator()(T&& t) | |||||
{ return Wrapper<clean_type<T>> { }; } | |||||
}; | |||||
constexpr auto my_tuple = make_basic_tuple(c_bool_t<false> { }, c_size_t<5> { }); | |||||
constexpr c_size_t<0> index0; | |||||
constexpr c_size_t<1> index1; | |||||
static_assert(unpack(my_tuple, op_unpack { }), ""); | |||||
static_assert(my_tuple.unpack(op_unpack { }), ""); | |||||
static_assert(decltype(at(my_tuple, index0))::value == false, ""); | |||||
static_assert(decltype(at(my_tuple, index1))::value == 5, ""); | |||||
static_assert(decltype(my_tuple.at(index0))::value == false, ""); | |||||
static_assert(decltype(my_tuple.at(index1))::value == 5, ""); | |||||
constexpr auto transformed = my_tuple.transform(op_transform { }); | |||||
using transformed_type = clean_type<decltype(transformed)>; | |||||
using transformed_expected = basic_tuple<Wrapper<c_bool_t<false>>, Wrapper<c_size_t<5>>>; | |||||
static_assert(is_same<transformed_type, transformed_expected>::value, ""); | |||||
} |
@@ -5,6 +5,6 @@ using namespace ::utl::mp::intern; | |||||
namespace test_mp_intern_has_value | namespace test_mp_intern_has_value | ||||
{ | { | ||||
static_assert( has_value<c_true>::value, ""); | |||||
static_assert( has_value<c_true_t>::value, ""); | |||||
static_assert(!has_value<bool>::value, ""); | static_assert(!has_value<bool>::value, ""); | ||||
} | } |
@@ -1,4 +1,4 @@ | |||||
#include <cpputils/mp/util/default.h> | |||||
#include <cpputils/mp/misc/default.h> | |||||
namespace test_mp_util_default | namespace test_mp_util_default | ||||
{ | { |
@@ -1,6 +1,6 @@ | |||||
#include <cstdint> | #include <cstdint> | ||||
#include <cpputils/mp/core/const.h> | #include <cpputils/mp/core/const.h> | ||||
#include <cpputils/mp/util/is_a.h> | |||||
#include <cpputils/mp/misc/is_a.h> | |||||
namespace test_mp_util_is_a | namespace test_mp_util_is_a | ||||
{ | { | ||||
@@ -14,5 +14,5 @@ using namespace ::test_mp_util_is_a; | |||||
static_assert( is_a<int, tagged_int>, "is_a"); | static_assert( is_a<int, tagged_int>, "is_a"); | ||||
static_assert(!is_a<int, tagged_float>, "is_a"); | static_assert(!is_a<int, tagged_float>, "is_a"); | ||||
static_assert( is_a<tag_const<int>>(integral_constant<int, 1> { }), "is_a"); | |||||
static_assert(!is_a<tag_const<int>>(integral_constant<uint8_t, 1> { }), "is_a"); | |||||
static_assert( is_a<tag_integral_constant<int>>(integral_constant<int, 1> { }), "is_a"); | |||||
static_assert(!is_a<tag_integral_constant<int>>(integral_constant<uint8_t, 1> { }), "is_a"); |
@@ -1,5 +1,5 @@ | |||||
#include <gtest/gtest.h> | #include <gtest/gtest.h> | ||||
#include <cpputils/mp/util/make.h> | |||||
#include <cpputils/mp/misc/make.h> | |||||
using namespace ::utl::mp; | using namespace ::utl::mp; | ||||
@@ -1,4 +1,4 @@ | |||||
#include <cpputils/mp/util/tag_of.h> | |||||
#include <cpputils/mp/misc/tag_of.h> | |||||
namespace test_mp_util_tag_of | namespace test_mp_util_tag_of | ||||
{ | { |
@@ -1,5 +1,5 @@ | |||||
#include <gtest/gtest.h> | #include <gtest/gtest.h> | ||||
#include <cpputils/mp/util/to.h> | |||||
#include <cpputils/mp/misc/to.h> | |||||
using namespace ::utl::mp; | using namespace ::utl::mp; | ||||
@@ -0,0 +1,9 @@ | |||||
#include <cpputils/mp/operations/logical/and.h> | |||||
using namespace ::utl::mp; | |||||
namespace test_mp_operations_logical_and | |||||
{ | |||||
static_assert( and_(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1), ""); | |||||
static_assert(!and_(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1), ""); | |||||
} |
@@ -0,0 +1,9 @@ | |||||
#include <cpputils/mp/operations/logical/or.h> | |||||
using namespace ::utl::mp; | |||||
namespace test_mp_operations_logical_or | |||||
{ | |||||
static_assert(!or_(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), ""); | |||||
static_assert( or_(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), ""); | |||||
} |
@@ -0,0 +1,9 @@ | |||||
#include <cpputils/mp/operations/value.h> | |||||
using namespace ::utl::mp; | |||||
namespace test_mp_operations_value | |||||
{ | |||||
constexpr integral_constant<int, 6> my_const{ }; | |||||
static_assert(value(my_const) == 6, ""); | |||||
} |