@@ -16,19 +16,19 @@ namespace utl | |||
template<class X, class Enable = void> | |||
struct __impl_cop_is_value : | |||
public mp::c_true { }; | |||
public mp::c_true; | |||
template<class X> | |||
struct __impl_cop_is_value<X*, void> : | |||
public mp::c_false { }; | |||
public mp::c_false; | |||
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>>>> : | |||
public mp::c_false { }; | |||
public mp::c_false; | |||
template<class X> | |||
struct __impl_cop_is_value<std::reference_wrapper<X>, void> : | |||
public mp::c_false { }; | |||
public mp::c_false; | |||
template<class X> | |||
using cop_is_value = __impl_cop_is_value<mp::clean_type<X>>; | |||
@@ -1,7 +1,7 @@ | |||
#pragma once | |||
#include <cpputils/mp/core.h> | |||
#include <cpputils/mp/util.h> | |||
#include <cpputils/mp/misc.h> | |||
#include <cpputils/mp/intern.h> | |||
#include <cpputils/mp/container.h> | |||
#include <cpputils/mp/operations.h> |
@@ -1,3 +1,6 @@ | |||
#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 | |||
#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/operators_orderable.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<1>, Second> | |||
{ | |||
using tag = tag_pair; | |||
using this_type = pair<First, Second>; | |||
// 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> | |||
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> | |||
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> | |||
using is_constructible = c_bool<std::is_constructible<T...>::value>; | |||
using is_constructible = c_bool_t<std::is_constructible<T...>::value>; | |||
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> | |||
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> | |||
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> | |||
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> | |||
using is_valid = __impl::is_valid_impl<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 */ | |||
{ | |||
template<typename...> | |||
struct is_valid_impl : | |||
public c_true | |||
public c_true_t | |||
{ }; | |||
} | |||
@@ -7,24 +7,31 @@ namespace utl { | |||
namespace mp { | |||
template<typename T> | |||
struct tag_const { }; | |||
struct tag_integral_constant { }; | |||
template<typename T, T t> | |||
struct integral_constant : | |||
public std::integral_constant<T, t> | |||
{ | |||
using tag = tag_const<T>; | |||
using tag = tag_integral_constant<T>; | |||
}; | |||
template<bool B> | |||
using c_bool = integral_constant<bool, B>; | |||
using c_bool_t = integral_constant<bool, B>; | |||
template<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 | |||
#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> | |||
struct comparable_equal | |||
: c_false | |||
: c_false_t | |||
{ }; | |||
template<typename 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)>> | |||
: c_true | |||
: c_true_t | |||
{ }; | |||
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<U>(std::declval<U>()) != std::forward<T>(std::declval<T>()) ? 0 : 0), | |||
common_type<T, U>>>> | |||
: c_bool< | |||
: c_bool_t< | |||
comparable_equal<T>::value && | |||
comparable_equal<U>::value && | |||
comparable_equal<common_type<T, U>>::value> | |||
@@ -9,13 +9,13 @@ namespace intern { | |||
template<typename T, typename U = T, typename = void> | |||
struct comparable_less | |||
: c_false | |||
: c_false_t | |||
{ }; | |||
template<typename T> | |||
struct comparable_less<T, T, void_t< | |||
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> | |||
@@ -25,7 +25,7 @@ namespace intern { | |||
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), | |||
common_type<T, U>>>> | |||
: c_bool< | |||
: c_bool_t< | |||
comparable_less<T>::value && | |||
comparable_less<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> | |||
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 <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/not_equal.h> | |||
@@ -2,7 +2,7 @@ | |||
#include <utility> | |||
#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_equal.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> | |||
struct is_default_impl : | |||
public c_false | |||
public c_false_t | |||
{ }; | |||
template<typename 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 | |||
#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 mp { |
@@ -2,8 +2,8 @@ | |||
#pragma once | |||
#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 mp { |
@@ -1,7 +1,7 @@ | |||
#pragma once | |||
#include <cpputils/mp/core/modifier.h> | |||
#include <cpputils/mp/util/when.h> | |||
#include <cpputils/mp/misc/when.h> | |||
namespace utl { | |||
namespace mp { |
@@ -1,7 +1,7 @@ | |||
#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> | |||
namespace utl { |
@@ -24,7 +24,7 @@ namespace mp { | |||
{ | |||
template<typename...> | |||
struct wrong_impl : | |||
public c_false | |||
public c_false_t | |||
{ }; | |||
} | |||
@@ -1,6 +1,15 @@ | |||
#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/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/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 | |||
#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/comparable_equal.h> | |||
#include <cpputils/mp/operations/if.h> | |||
@@ -36,7 +36,7 @@ namespace mp { | |||
{ | |||
template <typename ...Args> | |||
static constexpr auto apply(Args&& ...) | |||
{ return c_false { }; } | |||
{ return c_false; } | |||
}; | |||
template <typename T, typename U> | |||
@@ -55,7 +55,7 @@ namespace mp { | |||
{ | |||
constexpr auto eq = equal(value<X>(), value<Y>()); | |||
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 | |||
#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/compare/less.h> | |||
@@ -1,9 +1,9 @@ | |||
#pragma once | |||
#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/compare/less.h> | |||
@@ -1,9 +1,9 @@ | |||
#pragma once | |||
#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/comparable_less.h> | |||
#include <cpputils/mp/operations/if.h> | |||
@@ -36,7 +36,7 @@ namespace mp { | |||
{ | |||
template <typename ...Args> | |||
static constexpr auto apply(Args&& ...) | |||
{ return c_false { }; } | |||
{ return c_false; } | |||
}; | |||
template <typename T, typename U> | |||
@@ -55,7 +55,7 @@ namespace mp { | |||
{ | |||
constexpr auto eq = less(value<X>(), value<Y>()); | |||
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 | |||
#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/compare/less.h> | |||
@@ -1,9 +1,9 @@ | |||
#pragma once | |||
#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/compare/not_equal.h> | |||
@@ -1,9 +1,9 @@ | |||
#pragma once | |||
#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 mp { | |||
@@ -1,8 +1,8 @@ | |||
#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/operations/if.fwd.h> | |||
#include <cpputils/mp/operations/eval.h> | |||
@@ -51,11 +51,11 @@ namespace mp { | |||
struct eval_if_impl<T, when<intern::has_value<T>::value>> | |||
{ | |||
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)); } | |||
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)); } | |||
template <typename Cond, typename Then, typename Else> | |||
@@ -63,7 +63,7 @@ namespace mp { | |||
{ | |||
constexpr auto cond = value<Cond>(); | |||
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 | |||
#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 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/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> | |||
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 | |||
#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/intern/fold_left.h> | |||
namespace utl { | |||
namespace mp { | |||
@@ -46,17 +47,16 @@ namespace mp { | |||
using and_impl_type = and_impl<tag_type>; | |||
return and_impl_type::apply(std::forward<X>(x), std::forward<Y>(y)); | |||
}; | |||
/* TODO | |||
template <typename X, typename ...Y> | |||
constexpr auto and_t::operator()(X&& x, Y&& ...y) const | |||
{ | |||
return detail::variadic::foldl1( | |||
return intern::fold_left( | |||
*this, | |||
static_cast<X&&>(x), | |||
static_cast<Y&&>(y)... | |||
); | |||
} | |||
*/ | |||
} | |||
} |
@@ -1,9 +1,9 @@ | |||
#pragma once | |||
#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 mp { | |||
@@ -1,10 +1,11 @@ | |||
#pragma once | |||
#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/intern/fold_left.h> | |||
namespace utl { | |||
namespace mp { | |||
@@ -46,17 +47,16 @@ namespace mp { | |||
using or_impl_type = or_impl<tag_type>; | |||
return or_impl_type::apply(std::forward<X>(x), std::forward<Y>(y)); | |||
}; | |||
/* TODO | |||
template <typename X, typename ...Y> | |||
constexpr auto or_t::operator()(X&& x, Y&& ...y) const | |||
{ | |||
return detail::variadic::foldl1( | |||
return intern::fold_left( | |||
*this, | |||
static_cast<X&&>(x), | |||
static_cast<Y&&>(y)... | |||
); | |||
} | |||
*/ | |||
} | |||
} |
@@ -1,8 +1,8 @@ | |||
#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 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 | |||
#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 mp { | |||
@@ -42,7 +42,7 @@ namespace mp { | |||
}; | |||
template <typename T> | |||
struct value_impl<tag_const<T>> | |||
struct value_impl<tag_integral_constant<T>> | |||
{ | |||
template <typename C> | |||
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 | |||
{ | |||
static_assert( has_value<c_true>::value, ""); | |||
static_assert( has_value<c_true_t>::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 | |||
{ |
@@ -1,6 +1,6 @@ | |||
#include <cstdint> | |||
#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 | |||
{ | |||
@@ -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_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 <cpputils/mp/util/make.h> | |||
#include <cpputils/mp/misc/make.h> | |||
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 | |||
{ |
@@ -1,5 +1,5 @@ | |||
#include <gtest/gtest.h> | |||
#include <cpputils/mp/util/to.h> | |||
#include <cpputils/mp/misc/to.h> | |||
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, ""); | |||
} |