@@ -1,5 +0,0 @@ | |||||
#pragma once | |||||
#include <cpputils/container/handle_manager.h> | |||||
#include <cpputils/container/nullable.h> | |||||
#include <cpputils/container/smart_ptr.h> |
@@ -1,14 +0,0 @@ | |||||
#pragma once | |||||
#include <cpputils/misc/convert.h> | |||||
#include <cpputils/misc/enum.h> | |||||
#include <cpputils/misc/exception.h> | |||||
#include <cpputils/misc/flags.h> | |||||
#include <cpputils/misc/indent.h> | |||||
#include <cpputils/misc/misc.h> | |||||
#include <cpputils/misc/stream.h> | |||||
#include <cpputils/misc/string.h> | |||||
#include <cpputils/misc/time.h> | |||||
#include <cpputils/misc/transform_iterator.h> | |||||
#include <cpputils/misc/type_helper.h> | |||||
#include <cpputils/misc/wrapper.h> |
@@ -1,7 +1,3 @@ | |||||
#pragma once | #pragma once | ||||
#include <cpputils/mp/core.h> | |||||
#include <cpputils/mp/misc.h> | |||||
#include <cpputils/mp/intern.h> | |||||
#include <cpputils/mp/container.h> | |||||
#include <cpputils/mp/operations.h> | |||||
#include <cpputils/mp/core.h> |
@@ -1,34 +0,0 @@ | |||||
== License of this adaptation == | |||||
Copyright Erik Junghanns. | |||||
== Original boost::hana license == | |||||
Copyright Louis Dionne 2013-2017 | |||||
Boost Software License - Version 1.0 - August 17th, 2003 | |||||
Permission is hereby granted, free of charge, to any person or organization | |||||
obtaining a copy of the software and accompanying documentation covered by | |||||
this license (the "Software") to use, reproduce, display, distribute, | |||||
execute, and transmit the Software, and to prepare derivative works of the | |||||
Software, and to permit third-parties to whom the Software is furnished to | |||||
do so, all subject to the following: | |||||
The copyright notices in the Software and this entire statement, including | |||||
the above license grant, this restriction and the following disclaimer, | |||||
must be included in all copies of the Software, in whole or in part, and | |||||
all derivative works of the Software, unless such copies or derivative | |||||
works are solely in the form of machine-executable object code generated by | |||||
a source language processor. | |||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |||||
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT | |||||
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE | |||||
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, | |||||
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | |||||
DEALINGS IN THE SOFTWARE. | |||||
@@ -1,2 +0,0 @@ | |||||
This is an adaptation of the boost::hana library. | |||||
See https://github.com/boostorg/hana |
@@ -1,6 +0,0 @@ | |||||
#pragma once | |||||
#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> |
@@ -1,159 +0,0 @@ | |||||
#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)); } | |||||
} | |||||
} |
@@ -1,36 +0,0 @@ | |||||
#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,239 +0,0 @@ | |||||
#pragma once | |||||
#include <cpputils/mp/core.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> | |||||
#include <cpputils/mp/operations/first.h> | |||||
#include <cpputils/mp/operations/second.h> | |||||
#include <cpputils/mp/operations/compare/less.h> | |||||
#include <cpputils/mp/operations/compare/less_equal.h> | |||||
#include <cpputils/mp/operations/compare/equal.h> | |||||
#include <cpputils/mp/operations/logical/or.h> | |||||
#include <cpputils/mp/operations/logical/and.h> | |||||
#include <cpputils/mp/operations/logical/not.h> | |||||
namespace utl { | |||||
namespace mp { | |||||
struct tag_pair { }; | |||||
constexpr auto make_pair = make<tag_pair>; | |||||
namespace __impl | |||||
{ | |||||
template<int> | |||||
struct pair_index; | |||||
} | |||||
template<typename First, typename Second> | |||||
struct pair : | |||||
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 | |||||
template<typename... dummy, typename = enable_if_c< | |||||
is_constructible<First, dummy...>::value && | |||||
is_constructible<Second, dummy...>::value>> | |||||
constexpr pair() | |||||
: intern::ebo<__impl::pair_index<0>, First>() | |||||
, intern::ebo<__impl::pair_index<1>, Second>() | |||||
{ } | |||||
// variadic constructors | |||||
template<typename... dummy, typename = enable_if_c< | |||||
is_constructible<First, const First&, dummy...>::value && | |||||
is_constructible<Second, const Second&, dummy...>::value>> | |||||
constexpr pair(First f, Second s) | |||||
: intern::ebo<__impl::pair_index<0>, First>(f) | |||||
, intern::ebo<__impl::pair_index<1>, Second>(s) | |||||
{ } | |||||
template<typename F, typename S, typename = enable_if_c< | |||||
is_convertible<F&&, First>::value && | |||||
is_convertible<S&&, Second>::value>> | |||||
constexpr pair(F&& f, S&& s) | |||||
: intern::ebo<__impl::pair_index<0>, First>(std::forward<F>(f)) | |||||
, intern::ebo<__impl::pair_index<1>, Second>(std::forward<S>(s)) | |||||
{ } | |||||
// copy and move constructor | |||||
template<typename F, typename S, typename = enable_if_c< | |||||
is_constructible<First, const F&>::value && | |||||
is_constructible<Second, const S&>::value && | |||||
is_convertible<const F&, First>::value && | |||||
is_convertible<const S&, Second>::value>> | |||||
constexpr pair(const pair<F, S>& other) | |||||
: intern::ebo<__impl::pair_index<0>, First>(mp::first(other)) | |||||
, intern::ebo<__impl::pair_index<1>, Second>(mp::second(other)) | |||||
{ } | |||||
template<typename F, typename S, typename = enable_if_c< | |||||
is_constructible<First, const F&>::value && | |||||
is_constructible<Second, const S&>::value && | |||||
is_convertible<const F&, First>::value && | |||||
is_convertible<const S&, Second>::value>> | |||||
constexpr pair(pair<F, S>&& other) | |||||
: intern::ebo<__impl::pair_index<0>, First>(mp::first(std::forward<pair<F, S>>(other))) | |||||
, intern::ebo<__impl::pair_index<1>, Second>(mp::second(std::forward<pair<F, S>>(other))) | |||||
{ } | |||||
// copy and move assignment | |||||
template <typename F, typename S, typename = enable_if_c< | |||||
is_assignable<First&, const F&>::value && | |||||
is_assignable<Second&, const S&>::value>> | |||||
constexpr pair& operator=(const pair<F, S>& other) { | |||||
mp::first(*this) = mp::first(other); | |||||
mp::second(*this) = mp::second(other); | |||||
return *this; | |||||
} | |||||
template <typename F, typename S, typename = enable_if_c< | |||||
is_assignable<First&, const F &>::value && | |||||
is_assignable<Second&, const S &>::value>> | |||||
constexpr pair& operator=(pair<F, S>&& other) { | |||||
mp::first(*this) = mp::first(std::move<pair<F, S>>(other)); | |||||
mp::second(*this) = mp::second(std::move<pair<F, S>>(other)); | |||||
return *this; | |||||
} | |||||
constexpr auto first() const | |||||
{ return mp::first(*this); } | |||||
constexpr auto second() const | |||||
{ return mp::second(*this); } | |||||
// Prevent the compiler from defining the default copy and move | |||||
// constructors, which interfere with the SFINAE above. | |||||
~pair() = default; | |||||
friend struct __impl::first_impl<tag_pair>; | |||||
friend struct __impl::second_impl<tag_pair>; | |||||
}; | |||||
namespace intern { | |||||
template<> | |||||
struct operators_comparable<tag_pair> | |||||
{ static constexpr bool value = true; }; | |||||
template<> | |||||
struct operators_orderable<tag_pair> | |||||
{ static constexpr bool value = true; }; | |||||
} | |||||
namespace __impl | |||||
{ | |||||
/* tag_of */ | |||||
template<typename First, typename Second> | |||||
struct tag_of_impl<pair<First, Second>> | |||||
{ using type = tag_pair; }; | |||||
/* make */ | |||||
template<> | |||||
struct make_impl<tag_pair> | |||||
{ | |||||
template<typename F, typename S> | |||||
static constexpr pair<decay_type<F>, decay_type<S>> apply(F&& f, S&& s) | |||||
{ return { static_cast<F&&>(f), static_cast<S&&>(s) }; } | |||||
}; | |||||
/* first */ | |||||
template<> | |||||
struct first_impl<tag_pair> | |||||
{ | |||||
using type = int; | |||||
template<typename First, typename Second> | |||||
static constexpr auto apply(pair<First, Second>& p) | |||||
{ | |||||
return intern::ebo_get<pair_index<0>>( | |||||
static_cast<intern::ebo<pair_index<0>, First>&>(p) | |||||
); | |||||
} | |||||
template<typename First, typename Second> | |||||
static constexpr auto apply(pair<First, Second>&& p) | |||||
{ | |||||
return intern::ebo_get<pair_index<0>>( | |||||
static_cast<intern::ebo<pair_index<0>, First>&&>(p) | |||||
); | |||||
} | |||||
template<typename First, typename Second> | |||||
static constexpr auto apply(const pair<First, Second>& p) | |||||
{ | |||||
return intern::ebo_get<pair_index<0>>( | |||||
static_cast<const intern::ebo<pair_index<0>, First>&>(p) | |||||
); | |||||
} | |||||
}; | |||||
/* second */ | |||||
template<> | |||||
struct second_impl<tag_pair> | |||||
{ | |||||
template<typename First, typename Second> | |||||
static constexpr auto apply(pair<First, Second>& p) | |||||
{ | |||||
return intern::ebo_get<pair_index<1>>( | |||||
static_cast<intern::ebo<pair_index<1>, Second>&>(p) | |||||
); | |||||
} | |||||
template<typename First, typename Second> | |||||
static constexpr auto apply(pair<First, Second>&& p) | |||||
{ | |||||
return intern::ebo_get<pair_index<1>>( | |||||
static_cast<intern::ebo<pair_index<1>, Second>&&>(p) | |||||
); | |||||
} | |||||
template<typename First, typename Second> | |||||
static constexpr auto apply(const pair<First, Second>& p) | |||||
{ | |||||
return intern::ebo_get<pair_index<1>>( | |||||
static_cast<const intern::ebo<pair_index<1>, Second>&>(p) | |||||
); | |||||
} | |||||
}; | |||||
/* equal */ | |||||
template<> | |||||
struct equal_impl<tag_pair, tag_pair> | |||||
{ | |||||
template<typename L, typename R> | |||||
static constexpr auto apply(const L& l, const R& r) | |||||
{ | |||||
return and_( | |||||
equal(first(l), first(r)), | |||||
equal(second(l), second(r))); | |||||
} | |||||
}; | |||||
/* less */ | |||||
template<> | |||||
struct less_impl<tag_pair, tag_pair> | |||||
{ | |||||
template<typename L, typename R> | |||||
static constexpr auto apply(const L& l, const R& r) | |||||
{ | |||||
return or_( | |||||
less(first(l), first(r)), | |||||
and_( | |||||
less_equal(first (l), first (r)), | |||||
less (second(l), second(r)) | |||||
) | |||||
); | |||||
} | |||||
}; | |||||
} | |||||
} | |||||
} |
@@ -1,268 +0,0 @@ | |||||
#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; }; | |||||
} | |||||
} | |||||
} |
@@ -1,11 +0,0 @@ | |||||
#pragma once | |||||
#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> |
@@ -1,39 +0,0 @@ | |||||
#pragma once | |||||
#include <utility> | |||||
#include <cpputils/mp/core.h> | |||||
namespace utl { | |||||
namespace mp { | |||||
namespace intern { | |||||
template<typename T, typename U = T, typename = void> | |||||
struct comparable_equal | |||||
: 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_t | |||||
{ }; | |||||
template <typename T, typename U> | |||||
struct comparable_equal<T, U, enable_if_c< | |||||
!is_same<T, U>::value, | |||||
void_t< | |||||
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<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_t< | |||||
comparable_equal<T>::value && | |||||
comparable_equal<U>::value && | |||||
comparable_equal<common_type<T, U>>::value> | |||||
{ }; | |||||
} | |||||
} | |||||
} |
@@ -1,36 +0,0 @@ | |||||
#pragma once | |||||
#include <utility> | |||||
#include <cpputils/mp/core.h> | |||||
namespace utl { | |||||
namespace mp { | |||||
namespace intern { | |||||
template<typename T, typename U = T, typename = void> | |||||
struct comparable_less | |||||
: 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_t | |||||
{ }; | |||||
template <typename T, typename U> | |||||
struct comparable_less<T, U, enable_if_c< | |||||
!is_same<T, U>::value, | |||||
void_t< | |||||
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_t< | |||||
comparable_less<T>::value && | |||||
comparable_less<U>::value && | |||||
comparable_less<common_type<T, U>>::value> | |||||
{ }; | |||||
} | |||||
} | |||||
} |
@@ -1,83 +0,0 @@ | |||||
#pragma once | |||||
#include "../core.h" | |||||
namespace utl { | |||||
namespace mp { | |||||
namespace intern { | |||||
template<typename Key, typename Value, bool = is_empty<Value>::value && !is_final<Value>::value> | |||||
struct ebo; | |||||
template<typename Key, typename Value> | |||||
constexpr const Value& ebo_get(const ebo<Key, Value, true>& x) | |||||
{ return x; } | |||||
template<typename Key, typename Value> | |||||
constexpr Value& ebo_get(ebo<Key, Value, true>& x) | |||||
{ return x; } | |||||
template<typename Key, typename Value> | |||||
constexpr Value&& ebo_get(ebo<Key, Value, true>&& x) | |||||
{ return x; } | |||||
template<typename Key, typename Value> | |||||
constexpr const Value& ebo_get(const ebo<Key, Value, false>& x) | |||||
{ return x._data; } | |||||
template<typename Key, typename Value> | |||||
constexpr Value& ebo_get(ebo<Key, Value, false>& x) | |||||
{ return x._data; } | |||||
template<typename Key, typename Value> | |||||
constexpr Value&& ebo_get(ebo<Key, Value, false>&& x) | |||||
{ return static_cast<Value&&>(x._data); } | |||||
template<typename Key, typename Value> | |||||
struct ebo<Key, Value, true> : | |||||
public Value | |||||
{ | |||||
constexpr ebo() | |||||
{ } | |||||
template<typename T> | |||||
explicit constexpr ebo(T&& t) : | |||||
Value(std::forward<T>(t)) | |||||
{ } | |||||
constexpr auto get() const& | |||||
{ return ebo_get(*this); } | |||||
constexpr auto get() & | |||||
{ return ebo_get(*this); } | |||||
constexpr auto get() && | |||||
{ return ebo_get(std::move(*this)); } | |||||
}; | |||||
template<typename Key, typename Value> | |||||
struct ebo<Key, Value, false> | |||||
{ | |||||
Value _data; | |||||
constexpr ebo() | |||||
{ } | |||||
template<typename T> | |||||
explicit constexpr ebo(T&& t) : | |||||
_data(std::forward<T>(t)) | |||||
{ } | |||||
constexpr auto get() const& | |||||
{ return ebo_get(*this); } | |||||
constexpr auto get() & | |||||
{ return ebo_get(*this); } | |||||
constexpr auto get() && | |||||
{ return ebo_get(std::move(*this)); } | |||||
}; | |||||
} | |||||
} | |||||
} |
@@ -1,265 +0,0 @@ | |||||
#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 { }; | |||||
} | |||||
} | |||||
} |
@@ -1,244 +0,0 @@ | |||||
#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 { }; | |||||
} | |||||
} | |||||
} |
@@ -1,16 +0,0 @@ | |||||
#pragma once | |||||
#include <cpputils/mp/operations/value.h> | |||||
namespace utl { | |||||
namespace mp { | |||||
namespace intern { | |||||
template<typename C> | |||||
struct has_value | |||||
: c_bool_t<!is_default<::utl::mp::__impl::value_impl<tag_of<C>>>::value> | |||||
{ }; | |||||
} | |||||
} | |||||
} |
@@ -1,61 +0,0 @@ | |||||
#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>... | |||||
>; | |||||
}; | |||||
} | |||||
} | |||||
} |
@@ -1,36 +0,0 @@ | |||||
#pragma once | |||||
#include <utility> | |||||
#include <cpputils/mp/core/conditionals.h> | |||||
#include <cpputils/mp/misc/tag_of.h> | |||||
#include <cpputils/mp/operations/compare/equal.h> | |||||
#include <cpputils/mp/operations/compare/not_equal.h> | |||||
namespace utl { | |||||
namespace mp { | |||||
namespace intern { | |||||
template<typename T> | |||||
struct operators_comparable | |||||
{ static constexpr bool value = false; }; | |||||
} | |||||
namespace operators | |||||
{ | |||||
template<typename X, typename Y, typename = enable_if_c< | |||||
intern::operators_comparable<tag_of<X>>::value && | |||||
intern::operators_comparable<tag_of<Y>>::value>> | |||||
constexpr auto operator == (X&& x, Y&& y) | |||||
{ return equal(std::forward<X>(x), std::forward<Y>(y)); } | |||||
template<typename X, typename Y, typename = enable_if_c< | |||||
intern::operators_comparable<tag_of<X>>::value && | |||||
intern::operators_comparable<tag_of<Y>>::value>> | |||||
constexpr auto operator != (X&& x, Y&& y) | |||||
{ return not_equal(std::forward<X>(x), std::forward<Y>(y)); } | |||||
} | |||||
} | |||||
} |
@@ -1,50 +0,0 @@ | |||||
#pragma once | |||||
#include <utility> | |||||
#include <cpputils/mp/core/conditionals.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> | |||||
#include <cpputils/mp/operations/compare/greater_equal.h> | |||||
namespace utl { | |||||
namespace mp { | |||||
namespace intern { | |||||
template<typename T> | |||||
struct operators_orderable | |||||
{ static constexpr bool value = false; }; | |||||
} | |||||
namespace operators | |||||
{ | |||||
template<typename X, typename Y, typename = enable_if_c< | |||||
intern::operators_orderable<tag_of<X>>::value && | |||||
intern::operators_orderable<tag_of<Y>>::value>> | |||||
constexpr auto operator < (X&& x, Y&& y) | |||||
{ return less(std::forward<X>(x), std::forward<Y>(y)); } | |||||
template<typename X, typename Y, typename = enable_if_c< | |||||
intern::operators_orderable<tag_of<X>>::value && | |||||
intern::operators_orderable<tag_of<Y>>::value>> | |||||
constexpr auto operator <= (X&& x, Y&& y) | |||||
{ return less_equal(std::forward<X>(x), std::forward<Y>(y)); } | |||||
template<typename X, typename Y, typename = enable_if_c< | |||||
intern::operators_orderable<tag_of<X>>::value && | |||||
intern::operators_orderable<tag_of<Y>>::value>> | |||||
constexpr auto operator > (X&& x, Y&& y) | |||||
{ return greater(std::forward<X>(x), std::forward<Y>(y)); } | |||||
template<typename X, typename Y, typename = enable_if_c< | |||||
intern::operators_orderable<tag_of<X>>::value && | |||||
intern::operators_orderable<tag_of<Y>>::value>> | |||||
constexpr auto operator >= (X&& x, Y&& y) | |||||
{ return greater_equal(std::forward<X>(x), std::forward<Y>(y)); } | |||||
} | |||||
} | |||||
} |
@@ -1,8 +0,0 @@ | |||||
#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> |
@@ -1,33 +0,0 @@ | |||||
#pragma once | |||||
#include <cpputils/mp/core/const.h> | |||||
namespace utl { | |||||
namespace mp { | |||||
namespace __impl /* forward declaration */ | |||||
{ | |||||
template<typename T, typename = void> | |||||
struct is_default_impl; | |||||
} | |||||
template<typename T> | |||||
using is_default = __impl::is_default_impl<T>; | |||||
namespace __impl /* implementation */ | |||||
{ | |||||
struct default_ { }; | |||||
template<typename T, typename> | |||||
struct is_default_impl : | |||||
public c_false_t | |||||
{ }; | |||||
template<typename T> | |||||
struct is_default_impl<T, decltype((void)static_cast<default_>(std::declval<T>()))> : | |||||
public c_true_t | |||||
{ }; | |||||
} | |||||
} | |||||
} |
@@ -1,38 +0,0 @@ | |||||
#pragma once | |||||
#include <cpputils/mp/misc/when.h> | |||||
#include <cpputils/mp/misc/tag_of.h> | |||||
namespace utl { | |||||
namespace mp { | |||||
namespace __impl /* forward declaration */ | |||||
{ | |||||
template<typename Tag, typename ...T> | |||||
struct is_a_impl; | |||||
} | |||||
template<typename Tag, typename... T> | |||||
constexpr __impl::is_a_impl<Tag, T...> is_a { }; | |||||
template<typename Tag, typename... T> | |||||
constexpr __impl::is_a_impl<Tag, T...> is_an { }; | |||||
namespace __impl /* implementation */ | |||||
{ | |||||
template<typename Tag, typename T> | |||||
struct is_a_impl<Tag, T> : | |||||
public is_same<Tag, tag_of<T>> | |||||
{ }; | |||||
template<typename Tag> | |||||
struct is_a_impl<Tag> | |||||
{ | |||||
template<typename T> | |||||
constexpr auto operator()(const T&) const noexcept | |||||
{ return is_a<Tag, T>; } | |||||
}; | |||||
} | |||||
} | |||||
} |
@@ -1,55 +0,0 @@ | |||||
#pragma once | |||||
#include <utility> | |||||
#include <cpputils/mp/misc/when.h> | |||||
#include <cpputils/mp/misc/default.h> | |||||
namespace utl { | |||||
namespace mp { | |||||
namespace __impl /* forward declaration */ | |||||
{ | |||||
template<typename Tag> | |||||
struct make_t; | |||||
} | |||||
template<typename Tag> | |||||
constexpr __impl::make_t<Tag> make { }; | |||||
namespace __impl /* implementation */ | |||||
{ | |||||
template<typename T, typename = void> | |||||
struct make_impl : | |||||
public make_impl<T, when<true>> | |||||
{ }; | |||||
template<typename T, bool condition> | |||||
struct make_impl<T, when<condition>> : | |||||
public default_ | |||||
{ | |||||
template<typename... X> | |||||
static constexpr auto make_helper(int, X&&... x) | |||||
-> decltype(T(std::forward<X>(x)...)) | |||||
{ return T(std::forward<X>(x)...); } | |||||
template<typename... X> | |||||
static constexpr auto make_helper(long, X&&... x) | |||||
{ static_assert((sizeof...(X), false), "there exists no constructor for the given data type"); } | |||||
template <typename... X> | |||||
static constexpr auto apply(X&& ...x) | |||||
{ return make_helper(int{}, std::forward<X>(x)...); } | |||||
}; | |||||
template<typename T> | |||||
struct make_t | |||||
{ | |||||
template<typename... X> | |||||
constexpr auto operator()(X&&... x) const noexcept | |||||
{ return make_impl<T>::apply(std::forward<X>(x)...); } | |||||
}; | |||||
} | |||||
} | |||||
} |
@@ -1,35 +0,0 @@ | |||||
#pragma once | |||||
#include <cpputils/mp/core/modifier.h> | |||||
#include <cpputils/mp/misc/when.h> | |||||
namespace utl { | |||||
namespace mp { | |||||
namespace __impl /* forward declaration */ | |||||
{ | |||||
template<typename T, typename = void> | |||||
struct tag_of_impl; | |||||
} | |||||
template<typename T> | |||||
using tag_of = typename __impl::tag_of_impl<clean_type<T>>::type; | |||||
namespace __impl /* implementation */ | |||||
{ | |||||
template<typename T, typename> | |||||
struct tag_of_impl : | |||||
public tag_of_impl<T, when<true>> | |||||
{ }; | |||||
template<typename T, bool condition> | |||||
struct tag_of_impl<T, when<condition>> | |||||
{ using type = T; }; | |||||
template<typename T> | |||||
struct tag_of_impl<T, when_valid<typename clean_type<T>::tag>> | |||||
{ using type = typename clean_type<T>::tag; }; | |||||
} | |||||
} | |||||
} |
@@ -1,176 +0,0 @@ | |||||
#pragma once | |||||
#include <cpputils/mp/misc/when.h> | |||||
#include <cpputils/mp/misc/tag_of.h> | |||||
#include <cpputils/mp/core/conditionals.h> | |||||
namespace utl { | |||||
namespace mp { | |||||
namespace __impl /* forward declaration */ | |||||
{ | |||||
template<typename To> | |||||
struct to_t; | |||||
template <typename From, typename To, typename = void> | |||||
struct is_mp_convertible_impl; | |||||
template <typename From, typename To, typename = void> | |||||
struct is_embedded_impl; | |||||
} | |||||
template<typename To> | |||||
constexpr __impl::to_t<To> to { }; | |||||
template <typename From, typename To> | |||||
using is_mp_convertible = __impl::is_mp_convertible_impl<From, To>; | |||||
template <typename From, typename To> | |||||
using is_embedded = __impl::is_embedded_impl<From, To>; | |||||
namespace __impl /* implementation */ | |||||
{ | |||||
struct no_conversion { }; | |||||
template <bool = true> | |||||
struct embedding { }; | |||||
/* to_impl */ | |||||
template <typename To, typename From, typename = void> | |||||
struct to_impl; | |||||
template <typename To, typename From, typename> | |||||
struct to_impl : | |||||
public to_impl<To, From, when<true>> | |||||
{ }; | |||||
template <typename To, typename From, bool condition> | |||||
struct to_impl<To, From, when<condition>> : | |||||
public no_conversion | |||||
{ | |||||
template <typename X> | |||||
static constexpr auto apply(const X&) | |||||
{ static_assert(wrong<to_impl<To, From>, X> { }, "no conversion is available between the provided types"); } | |||||
}; | |||||
template <typename To, typename From> | |||||
struct to_impl<To, From, when_valid<decltype(static_cast<To>(std::declval<From>()))>> | |||||
{ | |||||
template <typename X> | |||||
static constexpr To apply(X&& x) | |||||
{ return static_cast<To>(std::forward<X>(x)); } | |||||
}; | |||||
template <typename To> | |||||
struct to_impl<To, To> : | |||||
public embedding<> | |||||
{ | |||||
template <typename X> | |||||
static constexpr X apply(X&& x) | |||||
{ return std::forward<X&&>(x); } | |||||
}; | |||||
template <typename T> | |||||
struct to_impl<T*, decltype(nullptr)> : | |||||
public embedding<> | |||||
{ | |||||
static constexpr T* apply(decltype(nullptr)) | |||||
{ return nullptr; } | |||||
}; | |||||
/* to_t */ | |||||
template <typename To> | |||||
struct to_t | |||||
{ | |||||
template <typename X> | |||||
constexpr auto operator()(X&& x) const | |||||
{ | |||||
using From = tag_of<X>; | |||||
return to_impl<To, From>::apply(std::forward<X>(x)); | |||||
} | |||||
}; | |||||
#define DEFINE_EMBEDDING_IMPL(TO, FROM) \ | |||||
template <> \ | |||||
struct to_impl<TO, FROM> : \ | |||||
public embedding<> \ | |||||
{ \ | |||||
static constexpr TO apply(FROM x) \ | |||||
{ return static_cast<TO>(x); } \ | |||||
} | |||||
DEFINE_EMBEDDING_IMPL(long double, double); | |||||
DEFINE_EMBEDDING_IMPL(long double, float); | |||||
DEFINE_EMBEDDING_IMPL(double , float); | |||||
DEFINE_EMBEDDING_IMPL(signed long long, signed long); | |||||
DEFINE_EMBEDDING_IMPL(signed long long, signed int); | |||||
DEFINE_EMBEDDING_IMPL(signed long long, signed short); | |||||
DEFINE_EMBEDDING_IMPL(signed long long, signed char); | |||||
DEFINE_EMBEDDING_IMPL(signed long , signed int); | |||||
DEFINE_EMBEDDING_IMPL(signed long , signed short); | |||||
DEFINE_EMBEDDING_IMPL(signed long , signed char); | |||||
DEFINE_EMBEDDING_IMPL(signed int , signed short); | |||||
DEFINE_EMBEDDING_IMPL(signed int , signed char); | |||||
DEFINE_EMBEDDING_IMPL(signed short , signed char); | |||||
DEFINE_EMBEDDING_IMPL(unsigned long long, unsigned long); | |||||
DEFINE_EMBEDDING_IMPL(unsigned long long, unsigned int); | |||||
DEFINE_EMBEDDING_IMPL(unsigned long long, unsigned short); | |||||
DEFINE_EMBEDDING_IMPL(unsigned long long, unsigned char); | |||||
DEFINE_EMBEDDING_IMPL(unsigned long , unsigned int); | |||||
DEFINE_EMBEDDING_IMPL(unsigned long , unsigned short); | |||||
DEFINE_EMBEDDING_IMPL(unsigned long , unsigned char); | |||||
DEFINE_EMBEDDING_IMPL(unsigned int , unsigned short); | |||||
DEFINE_EMBEDDING_IMPL(unsigned int , unsigned char); | |||||
DEFINE_EMBEDDING_IMPL(unsigned short , unsigned char); | |||||
#undef DEFINE_EMBEDDING_IMPL | |||||
template<class T> | |||||
using copy_char_signedness = if_t< | |||||
std::is_signed<char>, | |||||
typename std::make_signed<T>::type, | |||||
typename std::make_unsigned<T>::type>; | |||||
#define DEFINE_CHAR_EMBEDDING_IMPL(TO) \ | |||||
template <> \ | |||||
struct to_impl<copy_char_signedness<TO>, char> \ | |||||
: public embedding<> \ | |||||
{ \ | |||||
static constexpr copy_char_signedness<TO> apply(char x) \ | |||||
{ return static_cast<TO>(x); } \ | |||||
} | |||||
DEFINE_CHAR_EMBEDDING_IMPL(long long); | |||||
DEFINE_CHAR_EMBEDDING_IMPL(long); | |||||
DEFINE_CHAR_EMBEDDING_IMPL(int); | |||||
DEFINE_CHAR_EMBEDDING_IMPL(short); | |||||
#undef DEFINE_CHAR_EMBEDDING_IMPL | |||||
/* is_mp_convertible_impl */ | |||||
template <typename From, typename To, typename> | |||||
struct is_mp_convertible_impl : | |||||
public std::true_type | |||||
{ }; | |||||
template <typename From, typename To> | |||||
struct is_mp_convertible_impl<From, To, decltype((void) static_cast<no_conversion>(std::declval<to_impl<To, From>>()))> : | |||||
public std::false_type | |||||
{ }; | |||||
/* is_embedded_impl */ | |||||
template <typename From, typename To, typename> | |||||
struct is_embedded_impl : | |||||
public std::false_type | |||||
{ }; | |||||
template <typename From, typename To> | |||||
struct is_embedded_impl<From, To, decltype((void) static_cast<embedding<true>>(std::declval<to_impl<To, From>>()))> : | |||||
public std::true_type | |||||
{ }; | |||||
} | |||||
} | |||||
} |
@@ -1,32 +0,0 @@ | |||||
#pragma once | |||||
#include <cpputils/mp/core/checker.h> | |||||
namespace utl { | |||||
namespace mp { | |||||
namespace __impl /* forward declaration */ | |||||
{ | |||||
template<typename...> | |||||
struct wrong_impl; | |||||
} | |||||
template<bool condition> | |||||
struct when; | |||||
template<typename... T> | |||||
using when_valid = when<is_valid<T...>::value>; | |||||
template<typename... T> | |||||
using wrong = __impl::wrong_impl<T...>; | |||||
namespace __impl /* implementation */ | |||||
{ | |||||
template<typename...> | |||||
struct wrong_impl : | |||||
public c_false_t | |||||
{ }; | |||||
} | |||||
} | |||||
} |
@@ -1,15 +0,0 @@ | |||||
#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/transform.h> | |||||
#include <cpputils/mp/operations/unpack.h> | |||||
#include <cpputils/mp/operations/value.h> |
@@ -1,52 +0,0 @@ | |||||
#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,4 +0,0 @@ | |||||
#pragma once | |||||
#include <cpputils/mp/operations/compare/equal.h> | |||||
#include <cpputils/mp/operations/compare/not_equal.h> |
@@ -1,73 +0,0 @@ | |||||
#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/intern/has_value.h> | |||||
#include <cpputils/mp/intern/comparable_equal.h> | |||||
#include <cpputils/mp/operations/if.h> | |||||
#include <cpputils/mp/operations/value.h> | |||||
namespace utl { | |||||
namespace mp { | |||||
namespace __impl | |||||
{ | |||||
struct equal_t | |||||
{ | |||||
template<typename L, typename R> | |||||
constexpr auto operator()(const L& l, const R& r) const; | |||||
}; | |||||
} | |||||
constexpr __impl::equal_t equal { }; | |||||
namespace __impl | |||||
{ | |||||
template <typename L, typename R, typename = void> | |||||
struct equal_impl | |||||
: equal_impl<L, R, when<true>> | |||||
{ }; | |||||
template <typename L, typename R, bool condition> | |||||
struct equal_impl<L, R, when<condition>> | |||||
: default_ | |||||
{ | |||||
template <typename ...Args> | |||||
static constexpr auto apply(Args&& ...) | |||||
{ return c_false; } | |||||
}; | |||||
template <typename T, typename U> | |||||
struct equal_impl<T, U, when<intern::comparable_equal<T, U>::value>> | |||||
{ | |||||
template <typename X, typename Y> | |||||
static constexpr auto apply(X&& x, Y&& y) | |||||
{ return static_cast<X&&>(x) == static_cast<Y&&>(y); } | |||||
}; | |||||
template <typename C> | |||||
struct equal_impl<C, C, when<intern::has_value<C>::value>> | |||||
{ | |||||
template <typename X, typename Y> | |||||
static constexpr auto apply(const X&, const Y&) | |||||
{ | |||||
constexpr auto eq = equal(value<X>(), value<Y>()); | |||||
constexpr bool truth_value = if_ (eq, true, false); | |||||
return c_bool_t<truth_value> { }; | |||||
} | |||||
}; | |||||
template<typename L, typename R> | |||||
constexpr auto equal_t::operator()(const L& l, const R& r) const | |||||
{ | |||||
using l_tag_type = tag_of<L>; | |||||
using r_tag_type = tag_of<R>; | |||||
using equal_type = equal_impl<l_tag_type, r_tag_type>; | |||||
return equal_type::apply(l, r); | |||||
} | |||||
} | |||||
} | |||||
} |
@@ -1,51 +0,0 @@ | |||||
#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/logical/not.h> | |||||
#include <cpputils/mp/operations/compare/less.h> | |||||
namespace utl { | |||||
namespace mp { | |||||
namespace __impl | |||||
{ | |||||
struct greater_t | |||||
{ | |||||
template<typename L, typename R> | |||||
constexpr auto operator()(const L& l, const R& r) const; | |||||
}; | |||||
} | |||||
constexpr __impl::greater_t greater { }; | |||||
namespace __impl | |||||
{ | |||||
template <typename L, typename R, typename = void> | |||||
struct greater_impl | |||||
: greater_impl<L, R, when<true>> | |||||
{ }; | |||||
template <typename T, typename U, bool condition> | |||||
struct greater_impl<T, U, when<condition>> | |||||
: default_ | |||||
{ | |||||
template <typename X, typename Y> | |||||
static constexpr auto apply(X&& x, Y&& y) | |||||
{ return less(static_cast<Y&&>(y), static_cast<X&&>(x)); } | |||||
}; | |||||
template<typename L, typename R> | |||||
constexpr auto greater_t::operator()(const L& l, const R& r) const | |||||
{ | |||||
using l_tag_type = tag_of<L>; | |||||
using r_tag_type = tag_of<R>; | |||||
using greater_impl_type = greater_impl<l_tag_type, r_tag_type>; | |||||
return greater_impl_type::apply(l, r); | |||||
} | |||||
} | |||||
} | |||||
} |
@@ -1,51 +0,0 @@ | |||||
#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/logical/not.h> | |||||
#include <cpputils/mp/operations/compare/less.h> | |||||
namespace utl { | |||||
namespace mp { | |||||
namespace __impl | |||||
{ | |||||
struct greater_equal_t | |||||
{ | |||||
template<typename L, typename R> | |||||
constexpr auto operator()(const L& l, const R& r) const; | |||||
}; | |||||
} | |||||
constexpr __impl::greater_equal_t greater_equal { }; | |||||
namespace __impl | |||||
{ | |||||
template <typename L, typename R, typename = void> | |||||
struct greater_equal_impl | |||||
: greater_equal_impl<L, R, when<true>> | |||||
{ }; | |||||
template <typename T, typename U, bool condition> | |||||
struct greater_equal_impl<T, U, when<condition>> | |||||
: default_ | |||||
{ | |||||
template <typename X, typename Y> | |||||
static constexpr auto apply(X&& x, Y&& y) | |||||
{ return not_(less(static_cast<X&&>(x), static_cast<Y&&>(y))); } | |||||
}; | |||||
template<typename L, typename R> | |||||
constexpr auto greater_equal_t::operator()(const L& l, const R& r) const | |||||
{ | |||||
using l_tag_type = tag_of<L>; | |||||
using r_tag_type = tag_of<R>; | |||||
using greater_equal_impl_type = greater_equal_impl<l_tag_type, r_tag_type>; | |||||
return greater_equal_impl_type::apply(l, r); | |||||
} | |||||
} | |||||
} | |||||
} |
@@ -1,73 +0,0 @@ | |||||
#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/intern/has_value.h> | |||||
#include <cpputils/mp/intern/comparable_less.h> | |||||
#include <cpputils/mp/operations/if.h> | |||||
#include <cpputils/mp/operations/value.h> | |||||
namespace utl { | |||||
namespace mp { | |||||
namespace __impl | |||||
{ | |||||
struct less_t | |||||
{ | |||||
template<typename L, typename R> | |||||
constexpr auto operator()(const L& l, const R& r) const; | |||||
}; | |||||
} | |||||
constexpr __impl::less_t less { }; | |||||
namespace __impl | |||||
{ | |||||
template <typename L, typename R, typename = void> | |||||
struct less_impl | |||||
: less_impl<L, R, when<true>> | |||||
{ }; | |||||
template <typename L, typename R, bool condition> | |||||
struct less_impl<L, R, when<condition>> | |||||
: default_ | |||||
{ | |||||
template <typename ...Args> | |||||
static constexpr auto apply(Args&& ...) | |||||
{ return c_false; } | |||||
}; | |||||
template <typename T, typename U> | |||||
struct less_impl<T, U, when<intern::comparable_less<T, U>::value>> | |||||
{ | |||||
template <typename X, typename Y> | |||||
static constexpr auto apply(X&& x, Y&& y) | |||||
{ return static_cast<X&&>(x) < static_cast<Y&&>(y); } | |||||
}; | |||||
template <typename C> | |||||
struct less_impl<C, C, when<intern::has_value<C>::value>> | |||||
{ | |||||
template <typename X, typename Y> | |||||
static constexpr auto apply(const X&, const Y&) | |||||
{ | |||||
constexpr auto eq = less(value<X>(), value<Y>()); | |||||
constexpr bool truth_value = if_ (eq, true, false); | |||||
return c_bool_t<truth_value> { }; | |||||
} | |||||
}; | |||||
template<typename L, typename R> | |||||
constexpr auto less_t::operator()(const L& l, const R& r) const | |||||
{ | |||||
using l_tag_type = tag_of<L>; | |||||
using r_tag_type = tag_of<R>; | |||||
using less_type = less_impl<l_tag_type, r_tag_type>; | |||||
return less_type::apply(l, r); | |||||
} | |||||
} | |||||
} | |||||
} |
@@ -1,51 +0,0 @@ | |||||
#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/logical/not.h> | |||||
#include <cpputils/mp/operations/compare/less.h> | |||||
namespace utl { | |||||
namespace mp { | |||||
namespace __impl | |||||
{ | |||||
struct less_equal_t | |||||
{ | |||||
template<typename L, typename R> | |||||
constexpr auto operator()(const L& l, const R& r) const; | |||||
}; | |||||
} | |||||
constexpr __impl::less_equal_t less_equal { }; | |||||
namespace __impl | |||||
{ | |||||
template <typename L, typename R, typename = void> | |||||
struct less_equal_impl | |||||
: less_equal_impl<L, R, when<true>> | |||||
{ }; | |||||
template <typename T, typename U, bool condition> | |||||
struct less_equal_impl<T, U, when<condition>> | |||||
: default_ | |||||
{ | |||||
template <typename X, typename Y> | |||||
static constexpr auto apply(X&& x, Y&& y) | |||||
{ return not_(less(static_cast<Y&&>(y), static_cast<X&&>(x))); } | |||||
}; | |||||
template<typename L, typename R> | |||||
constexpr auto less_equal_t::operator()(const L& l, const R& r) const | |||||
{ | |||||
using l_tag_type = tag_of<L>; | |||||
using r_tag_type = tag_of<R>; | |||||
using less_equal_impl_type = less_equal_impl<l_tag_type, r_tag_type>; | |||||
return less_equal_impl_type::apply(l, r); | |||||
} | |||||
} | |||||
} | |||||
} |
@@ -1,51 +0,0 @@ | |||||
#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/logical/not.h> | |||||
#include <cpputils/mp/operations/compare/not_equal.h> | |||||
namespace utl { | |||||
namespace mp { | |||||
namespace __impl | |||||
{ | |||||
struct not_equal_t | |||||
{ | |||||
template<typename L, typename R> | |||||
constexpr auto operator()(const L& l, const R& r) const; | |||||
}; | |||||
} | |||||
constexpr __impl::not_equal_t not_equal { }; | |||||
namespace __impl | |||||
{ | |||||
template <typename L, typename R, typename = void> | |||||
struct not_equal_impl | |||||
: not_equal_impl<L, R, when<true>> | |||||
{ }; | |||||
template <typename L, typename R, bool condition> | |||||
struct not_equal_impl<L, R, when<condition>> | |||||
: default_ | |||||
{ | |||||
template <typename X, typename Y> | |||||
static constexpr auto apply(X&& x, Y&& y) | |||||
{ return not(equal(std::forward<X>(x), std::forward<Y>(y))); } | |||||
}; | |||||
template<typename L, typename R> | |||||
constexpr auto not_equal_t::operator()(const L& l, const R& r) const | |||||
{ | |||||
using l_tag_type = tag_of<L>; | |||||
using r_tag_type = tag_of<R>; | |||||
using not_equal_type = not_equal_impl<l_tag_type, r_tag_type>; | |||||
return not_equal_type::apply(l, r); | |||||
} | |||||
} | |||||
} | |||||
} |
@@ -1,59 +0,0 @@ | |||||
#pragma once | |||||
#include <utility> | |||||
#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 eval_t | |||||
{ | |||||
template <typename Expr> | |||||
constexpr auto operator()(Expr&& expr) const; | |||||
}; | |||||
} | |||||
constexpr __impl::eval_t eval { }; | |||||
namespace __impl | |||||
{ | |||||
template <typename T, typename = void> | |||||
struct eval_impl | |||||
: eval_impl<T, when<true>> | |||||
{ }; | |||||
template <typename T, bool condition> | |||||
struct eval_impl<T, when<condition>> | |||||
: default_ | |||||
{ | |||||
template <typename Expr> | |||||
static constexpr auto eval_helper(Expr&& expr, int) | |||||
{ return static_cast<Expr&&>(expr)(); } | |||||
template <typename Expr> | |||||
static constexpr auto eval_helper(Expr&&, ...) | |||||
{ | |||||
static_assert(wrong<Expr> { }, | |||||
"eval(expr) requires the expression to be a a nullary Callable"); | |||||
} | |||||
template <typename Expr> | |||||
static constexpr decltype(auto) apply(Expr&& expr) | |||||
{ return eval_helper(static_cast<Expr&&>(expr), int { }); } | |||||
}; | |||||
template <typename Expr> | |||||
constexpr auto eval_t::operator()(Expr&& expr) const | |||||
{ | |||||
using tag_type = tag_of<Expr>; | |||||
using eval_impl_type = eval_impl<tag_type>; | |||||
return eval_impl_type::apply(std::forward<Expr>(expr));; | |||||
} | |||||
} | |||||
} | |||||
} |
@@ -1,80 +0,0 @@ | |||||
#pragma once | |||||
#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> | |||||
namespace utl { | |||||
namespace mp { | |||||
namespace __impl | |||||
{ | |||||
struct eval_if_t | |||||
{ | |||||
template <typename Cond, typename Then, typename Else> | |||||
constexpr auto operator()(Cond&& c, Then&& t, Else&& e) const; | |||||
}; | |||||
} | |||||
constexpr __impl::eval_if_t eval_if { }; | |||||
namespace __impl | |||||
{ | |||||
template <typename T, typename = void> | |||||
struct eval_if_impl | |||||
: eval_if_impl<T, when<true>> | |||||
{ }; | |||||
template <typename T, bool condition> | |||||
struct eval_if_impl<T, when<condition>> | |||||
: default_ | |||||
{ | |||||
template <typename ...Args> | |||||
static constexpr auto apply(Args&& ...) = delete; | |||||
}; | |||||
template <typename T> | |||||
struct eval_if_impl<T, when<is_arithmetic<T>::value>> | |||||
{ | |||||
template <typename Cond, typename Then, typename Else> | |||||
static constexpr auto apply(const Cond& cond, Then&& t, Else&& e) | |||||
{ | |||||
return cond ? eval(std::forward<Then>(t)) | |||||
: eval(std::forward<Else>(e)); | |||||
} | |||||
}; | |||||
template <typename T> | |||||
struct eval_if_impl<T, when<intern::has_value<T>::value>> | |||||
{ | |||||
template<typename Then, typename Else> | |||||
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_t, Then&& t, Else&& e) | |||||
{ return eval(std::forward<Else>(e)); } | |||||
template <typename Cond, typename Then, typename Else> | |||||
static constexpr auto apply(const Cond&, Then&& t, Else&& e) | |||||
{ | |||||
constexpr auto cond = value<Cond>(); | |||||
constexpr bool truth_value = if_(cond, true, false); | |||||
return eval_if_helper(c_bool_t<truth_value> { }, std::forward<Then>(t), std::forward<Else>(e)); | |||||
} | |||||
}; | |||||
template <typename Cond, typename Then, typename Else> | |||||
constexpr auto eval_if_t::operator()(Cond&& c, Then&& t, Else&& e) const | |||||
{ | |||||
using tag_type = tag_of<Cond>; | |||||
using eval_if_type = eval_if_impl<tag_type>; | |||||
return eval_if_type::apply(std::forward<Cond>(c), std::forward<Then>(t), std::forward<Else>(e)); | |||||
} | |||||
} | |||||
} | |||||
} |
@@ -1,46 +0,0 @@ | |||||
#pragma once | |||||
#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 first_t | |||||
{ | |||||
template<typename T> | |||||
constexpr auto operator()(T&& t) const; | |||||
}; | |||||
} | |||||
constexpr __impl::first_t first { }; | |||||
namespace __impl | |||||
{ | |||||
template <typename T, typename = void> | |||||
struct first_impl | |||||
: first_impl<T, when<true>> | |||||
{ }; | |||||
template <typename T, bool condition> | |||||
struct first_impl<T, when<condition>> | |||||
: default_ | |||||
{ | |||||
template <typename ...Args> | |||||
static constexpr auto apply(Args&& ...) = delete; | |||||
}; | |||||
template<typename T> | |||||
constexpr auto first_t::operator()(T&& t) const | |||||
{ | |||||
using tag_type = tag_of<T>; | |||||
using first_type = first_impl<tag_type>; | |||||
return first_type::apply(std::forward<T>(t)); | |||||
} | |||||
} | |||||
} | |||||
} |
@@ -1,28 +0,0 @@ | |||||
#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 { }; | |||||
} | |||||
} |
@@ -1,104 +0,0 @@ | |||||
#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); | |||||
} | |||||
} | |||||
} | |||||
} |
@@ -1,18 +0,0 @@ | |||||
#pragma once | |||||
namespace utl { | |||||
namespace mp { | |||||
namespace __impl | |||||
{ | |||||
struct if_t | |||||
{ | |||||
template <typename Cond, typename Then, typename Else> | |||||
constexpr auto operator()(Cond&& c, Then&& t, Else&& e) const; | |||||
}; | |||||
} | |||||
constexpr __impl::if_t if_ { }; | |||||
} | |||||
} |
@@ -1,52 +0,0 @@ | |||||
#pragma once | |||||
#include <cpputils/mp/operations/if.fwd.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 { | |||||
namespace mp { | |||||
namespace __impl | |||||
{ | |||||
template <typename T> | |||||
struct hold { | |||||
T value; | |||||
constexpr T&& operator()() && | |||||
{ return static_cast<T&&>(value); } | |||||
}; | |||||
template <typename L, typename = void> | |||||
struct if_impl | |||||
: if_impl<L, when<true>> | |||||
{ }; | |||||
template <typename L, bool condition> | |||||
struct if_impl<L, when<condition>> | |||||
: default_ | |||||
{ | |||||
template <typename Cond, typename Then, typename Else> | |||||
static constexpr auto apply(Cond&& c, Then&& t, Else&& e) | |||||
{ | |||||
return eval_if( | |||||
std::forward<Cond>(c), | |||||
hold<Then&&> { static_cast<Then&&>(t) }, | |||||
hold<Else&&> { static_cast<Else&&>(e) } | |||||
); | |||||
} | |||||
}; | |||||
template <typename Cond, typename Then, typename Else> | |||||
constexpr auto if_t::operator()(Cond&& c, Then&& t, Else&& e) const | |||||
{ | |||||
using tag_type = tag_of<Cond>; | |||||
using if_type = if_impl<tag_type>; | |||||
return if_type::apply(std::forward<Cond>(c), std::forward<Then>(t), std::forward<Else>(e)); | |||||
} | |||||
} | |||||
} | |||||
} |
@@ -1,56 +0,0 @@ | |||||
#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,4 +0,0 @@ | |||||
#pragma once | |||||
#include <cpputils/mp/operations/logical/not.h> | |||||
#include <cpputils/mp/operations/logical/and.h> |
@@ -1,63 +0,0 @@ | |||||
#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/if.h> | |||||
#include <cpputils/mp/intern/fold_left.h> | |||||
namespace utl { | |||||
namespace mp { | |||||
namespace __impl | |||||
{ | |||||
struct and_t | |||||
{ | |||||
template<typename X, typename Y> | |||||
constexpr auto operator()(X&& x, Y&& y) const; | |||||
template<typename X, typename... Y> | |||||
constexpr auto operator()(X&& x, Y&&... y) const; | |||||
}; | |||||
} | |||||
constexpr __impl::and_t and_ { }; | |||||
namespace __impl | |||||
{ | |||||
template <typename T, typename = void> | |||||
struct and_impl | |||||
: and_impl<T, when<true>> | |||||
{ }; | |||||
template <typename T, bool condition> | |||||
struct and_impl<T, when<condition>> | |||||
: default_ | |||||
{ | |||||
template <typename X, typename Y> | |||||
static constexpr auto apply(X&& x, Y&& y) | |||||
{ return if_(x, static_cast<Y&&>(y), x); } | |||||
}; | |||||
template <typename X, typename Y> | |||||
constexpr auto and_t::operator()(X&& x, Y&& y) const | |||||
{ | |||||
using tag_type = tag_of<X>; | |||||
using and_impl_type = and_impl<tag_type>; | |||||
return and_impl_type::apply(std::forward<X>(x), std::forward<Y>(y)); | |||||
}; | |||||
template <typename X, typename ...Y> | |||||
constexpr auto and_t::operator()(X&& x, Y&& ...y) const | |||||
{ | |||||
return intern::fold_left( | |||||
*this, | |||||
static_cast<X&&>(x), | |||||
static_cast<Y&&>(y)... | |||||
); | |||||
} | |||||
} | |||||
} | |||||
} |
@@ -1,55 +0,0 @@ | |||||
#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> | |||||
namespace utl { | |||||
namespace mp { | |||||
namespace __impl | |||||
{ | |||||
struct not_t | |||||
{ | |||||
template<typename X> | |||||
constexpr auto operator()(X&& x) const; | |||||
}; | |||||
} | |||||
constexpr __impl::not_t not_ { }; | |||||
namespace __impl | |||||
{ | |||||
template <typename T, typename = void> | |||||
struct not_impl | |||||
: not_impl<T, when<true>> | |||||
{ }; | |||||
template <typename T, bool condition> | |||||
struct not_impl<T, when<condition>> | |||||
: default_ | |||||
{ | |||||
template <typename ...Args> | |||||
static constexpr auto apply(Args&& ...) = delete; | |||||
}; | |||||
template <typename T> | |||||
struct not_impl<T, when<is_arithmetic<T>::value>> | |||||
{ | |||||
template <typename X> | |||||
static constexpr auto apply(const X& x) | |||||
{ return x ? false : true; } | |||||
}; | |||||
template <typename X> | |||||
constexpr auto not_t::operator()(X&& x) const | |||||
{ | |||||
using tag_type = tag_of<X>; | |||||
using not_impl_type = not_impl<tag_type>; | |||||
return not_impl_type::apply(std::forward<X>(x)); | |||||
}; | |||||
} | |||||
} | |||||
} |
@@ -1,63 +0,0 @@ | |||||
#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/if.h> | |||||
#include <cpputils/mp/intern/fold_left.h> | |||||
namespace utl { | |||||
namespace mp { | |||||
namespace __impl | |||||
{ | |||||
struct or_t | |||||
{ | |||||
template<typename X, typename Y> | |||||
constexpr auto operator()(X&& x, Y&& y) const; | |||||
template<typename X, typename... Y> | |||||
constexpr auto operator()(X&& x, Y&&... y) const; | |||||
}; | |||||
} | |||||
constexpr __impl::or_t or_ { }; | |||||
namespace __impl | |||||
{ | |||||
template <typename T, typename = void> | |||||
struct or_impl | |||||
: or_impl<T, when<true>> | |||||
{ }; | |||||
template <typename T, bool condition> | |||||
struct or_impl<T, when<condition>> | |||||
: default_ | |||||
{ | |||||
template <typename X, typename Y> | |||||
static constexpr auto apply(X&& x, Y&& y) | |||||
{ return if_(x, x, static_cast<Y&&>(y)); } | |||||
}; | |||||
template <typename X, typename Y> | |||||
constexpr auto or_t::operator()(X&& x, Y&& y) const | |||||
{ | |||||
using tag_type = tag_of<X>; | |||||
using or_impl_type = or_impl<tag_type>; | |||||
return or_impl_type::apply(std::forward<X>(x), std::forward<Y>(y)); | |||||
}; | |||||
template <typename X, typename ...Y> | |||||
constexpr auto or_t::operator()(X&& x, Y&& ...y) const | |||||
{ | |||||
return intern::fold_left( | |||||
*this, | |||||
static_cast<X&&>(x), | |||||
static_cast<Y&&>(y)... | |||||
); | |||||
} | |||||
} | |||||
} | |||||
} |
@@ -1,46 +0,0 @@ | |||||
#pragma once | |||||
#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 second_t | |||||
{ | |||||
template<typename T> | |||||
constexpr auto operator()(T&& t) const; | |||||
}; | |||||
} | |||||
constexpr __impl::second_t second { }; | |||||
namespace __impl | |||||
{ | |||||
template <typename T, typename = void> | |||||
struct second_impl | |||||
: second_impl<T, when<true>> | |||||
{ }; | |||||
template <typename T, bool condition> | |||||
struct second_impl<T, when<condition>> | |||||
: default_ | |||||
{ | |||||
template <typename ...Args> | |||||
static constexpr auto apply(Args&& ...) = delete; | |||||
}; | |||||
template<typename T> | |||||
constexpr auto second_t::operator()(T&& t) const | |||||
{ | |||||
using tag = tag_of<T>; | |||||
using second = second_impl<tag>; | |||||
return second::apply(std::forward<T>(t)); | |||||
} | |||||
} | |||||
} | |||||
} |
@@ -1,68 +0,0 @@ | |||||
#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)); | |||||
} | |||||
} | |||||
} | |||||
} |
@@ -1,18 +0,0 @@ | |||||
#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 { }; | |||||
} | |||||
} |
@@ -1,61 +0,0 @@ | |||||
#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,54 +0,0 @@ | |||||
#pragma once | |||||
#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 | |||||
{ | |||||
template<typename T, typename = void> | |||||
struct value_impl; | |||||
} | |||||
template <typename T> | |||||
constexpr auto value() | |||||
{ | |||||
using t_clean_type = clean_type<T>; | |||||
using tag_type = tag_of<T>; | |||||
using value_impl_type = __impl::value_impl<tag_type>; | |||||
return value_impl_type::template apply<t_clean_type>(); | |||||
} | |||||
template <typename T> | |||||
constexpr decltype(auto) value(T const&) | |||||
{ return value<T>(); } | |||||
namespace __impl | |||||
{ | |||||
template <typename T, typename> | |||||
struct value_impl | |||||
: value_impl<T, when<true>> | |||||
{ }; | |||||
template <typename T, bool condition> | |||||
struct value_impl<T, when<condition>> | |||||
: default_ | |||||
{ | |||||
template <typename ...Args> | |||||
static constexpr auto apply(Args&& ...args) = delete; | |||||
}; | |||||
template <typename T> | |||||
struct value_impl<tag_integral_constant<T>> | |||||
{ | |||||
template <typename C> | |||||
static constexpr auto apply() | |||||
{ return C::value; } | |||||
}; | |||||
} | |||||
} | |||||
} |
@@ -1,41 +0,0 @@ | |||||
#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, ""); | |||||
} |
@@ -1,61 +0,0 @@ | |||||
#include <cpputils/mp/container/pair.h> | |||||
#include <cpputils/mp/operations/compare/equal.h> | |||||
#include <cpputils/mp/operations/compare/not_equal.h> | |||||
#include <cpputils/mp/operations/compare/less.h> | |||||
#include <cpputils/mp/operations/compare/less_equal.h> | |||||
#include <cpputils/mp/operations/compare/greater.h> | |||||
#include <cpputils/mp/operations/compare/greater_equal.h> | |||||
using namespace ::utl::mp; | |||||
using namespace ::utl::mp::operators; | |||||
namespace test_mp_container_pair | |||||
{ | |||||
constexpr auto my_pair = make_pair(1, 'x'); | |||||
static_assert(first(my_pair) == 1, ""); | |||||
static_assert(second(my_pair) == 'x', ""); | |||||
static_assert(my_pair.first() == 1, ""); | |||||
static_assert(my_pair.second() == 'x', ""); | |||||
static_assert(equal(make_pair(1, 'x'), make_pair(1, 'x')), ""); | |||||
static_assert( make_pair(1, 'x') == make_pair(1, 'x'), ""); | |||||
static_assert(not_equal(make_pair(1, 'x'), make_pair(2, 'x')), ""); | |||||
static_assert( make_pair(1, 'x') != make_pair(2, 'x'), ""); | |||||
static_assert(less(make_pair(1, 'x'), make_pair(1, 'y')), ""); | |||||
static_assert(less(make_pair(1, 'x'), make_pair(2, 'x')), ""); | |||||
static_assert(less(make_pair(1, 'x'), make_pair(2, 'a')), ""); | |||||
static_assert(make_pair(1, 'x') < make_pair(1, 'y'), ""); | |||||
static_assert(make_pair(1, 'x') < make_pair(2, 'x'), ""); | |||||
static_assert(make_pair(1, 'x') < make_pair(2, 'a'), ""); | |||||
static_assert(less_equal(make_pair(1, 'x'), make_pair(1, 'x')), ""); | |||||
static_assert(less_equal(make_pair(1, 'x'), make_pair(1, 'y')), ""); | |||||
static_assert(less_equal(make_pair(1, 'x'), make_pair(2, 'x')), ""); | |||||
static_assert(less_equal(make_pair(1, 'x'), make_pair(2, 'a')), ""); | |||||
static_assert(make_pair(1, 'x') <= make_pair(1, 'x'), ""); | |||||
static_assert(make_pair(1, 'x') <= make_pair(1, 'y'), ""); | |||||
static_assert(make_pair(1, 'x') <= make_pair(2, 'x'), ""); | |||||
static_assert(make_pair(1, 'x') <= make_pair(2, 'a'), ""); | |||||
static_assert(greater(make_pair(1, 'y'), make_pair(1, 'x')), ""); | |||||
static_assert(greater(make_pair(2, 'x'), make_pair(1, 'x')), ""); | |||||
static_assert(greater(make_pair(2, 'a'), make_pair(1, 'x')), ""); | |||||
static_assert(make_pair(1, 'y') > make_pair(1, 'x'), ""); | |||||
static_assert(make_pair(2, 'x') > make_pair(1, 'x'), ""); | |||||
static_assert(make_pair(2, 'a') > make_pair(1, 'x'), ""); | |||||
static_assert(greater_equal(make_pair(1, 'x'), make_pair(1, 'x')), ""); | |||||
static_assert(greater_equal(make_pair(1, 'y'), make_pair(1, 'x')), ""); | |||||
static_assert(greater_equal(make_pair(2, 'x'), make_pair(1, 'x')), ""); | |||||
static_assert(greater_equal(make_pair(2, 'a'), make_pair(1, 'x')), ""); | |||||
static_assert(make_pair(1, 'x') >= make_pair(1, 'x'), ""); | |||||
static_assert(make_pair(1, 'y') >= make_pair(1, 'x'), ""); | |||||
static_assert(make_pair(2, 'x') >= make_pair(1, 'x'), ""); | |||||
static_assert(make_pair(2, 'a') >= make_pair(1, 'x'), ""); | |||||
} |
@@ -1,8 +0,0 @@ | |||||
#include <cpputils/mp/intern/comparable_equal.h> | |||||
using namespace ::utl::mp::intern; | |||||
namespace test_mp_intern_comparable_equal | |||||
{ | |||||
static_assert(comparable_equal<bool, bool>::value, ""); | |||||
} |
@@ -1,9 +0,0 @@ | |||||
#include <gtest/gtest.h> | |||||
#include <cpputils/mp/intern/ebo.h> | |||||
using namespace ::utl::mp::intern; | |||||
struct Key { }; | |||||
using ebo_type = ebo<Key, int>; | |||||
constexpr ebo_type myEbo(7); | |||||
static_assert(myEbo.get() == 7, "ebo.get"); |
@@ -1,10 +0,0 @@ | |||||
#include <cpputils/mp/intern/has_value.h> | |||||
using namespace ::utl::mp; | |||||
using namespace ::utl::mp::intern; | |||||
namespace test_mp_intern_has_value | |||||
{ | |||||
static_assert( has_value<c_true_t>::value, ""); | |||||
static_assert(!has_value<bool>::value, ""); | |||||
} |
@@ -1,14 +0,0 @@ | |||||
#include <cpputils/mp/misc/default.h> | |||||
namespace test_mp_util_default | |||||
{ | |||||
struct is_default_true : public ::utl::mp::__impl::default_ { }; | |||||
struct is_default_false { }; | |||||
} | |||||
using namespace ::utl::mp; | |||||
using namespace ::test_mp_util_default; | |||||
static_assert( is_default<is_default_true>::value, ""); | |||||
static_assert(!is_default<is_default_false>::value, ""); | |||||
static_assert(!is_default<bool>::value, ""); |
@@ -1,18 +0,0 @@ | |||||
#include <cstdint> | |||||
#include <cpputils/mp/core/const.h> | |||||
#include <cpputils/mp/misc/is_a.h> | |||||
namespace test_mp_util_is_a | |||||
{ | |||||
struct tagged_int { using tag = int; }; | |||||
struct tagged_float { using tag = float; }; | |||||
struct tagged_not { }; | |||||
} | |||||
using namespace ::utl::mp; | |||||
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_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,9 +0,0 @@ | |||||
#include <gtest/gtest.h> | |||||
#include <cpputils/mp/misc/make.h> | |||||
using namespace ::utl::mp; | |||||
TEST(mp_util_test, make) | |||||
{ | |||||
EXPECT_EQ(std::string("fuu"), make<std::string>("fuu")); | |||||
} |
@@ -1,27 +0,0 @@ | |||||
#include <cpputils/mp/misc/tag_of.h> | |||||
namespace test_mp_util_tag_of | |||||
{ | |||||
struct tagged_int { using tag = int; }; | |||||
struct tagged_float { using tag = float; }; | |||||
struct tagged_not { }; | |||||
} | |||||
using namespace ::utl::mp; | |||||
using namespace ::test_mp_util_tag_of; | |||||
using tagged_0_expected = int; | |||||
using tagged_0_actual = tag_of<tagged_int>; | |||||
static_assert(is_same<tagged_0_expected, tagged_0_actual>::value, ""); | |||||
using tagged_1_expected = float; | |||||
using tagged_1_actual = tag_of<tagged_float>; | |||||
static_assert(is_same<tagged_1_expected, tagged_1_actual>::value, ""); | |||||
using not_tagged_expected = tagged_not; | |||||
using not_tagged_actual = tag_of<tagged_not>; | |||||
static_assert(is_same<not_tagged_expected, not_tagged_actual>::value, ""); | |||||
using bool_expected = bool; | |||||
using bool_actual = tag_of<bool>; | |||||
static_assert(is_same<bool_expected, bool_actual>::value, ""); |
@@ -1,39 +0,0 @@ | |||||
#include <gtest/gtest.h> | |||||
#include <cpputils/mp/misc/to.h> | |||||
using namespace ::utl::mp; | |||||
static_assert(is_convertible<int32_t, int8_t>::value, "is_convertible"); | |||||
static_assert(is_convertible<uint32_t, int8_t>::value, "is_convertible"); | |||||
static_assert(!is_convertible<std::string, int8_t>::value, "is_convertible"); | |||||
static_assert(is_embedded<double, long double>::value, "is_embdedded"); | |||||
static_assert(is_embedded<float, long double>::value, "is_embdedded"); | |||||
static_assert(is_embedded<float, double >::value, "is_embdedded"); | |||||
static_assert(is_embedded<signed long, signed long long>::value, "is_embedded"); | |||||
static_assert(is_embedded<signed int, signed long long>::value, "is_embedded"); | |||||
static_assert(is_embedded<signed short, signed long long>::value, "is_embedded"); | |||||
static_assert(is_embedded<signed char, signed long long>::value, "is_embedded"); | |||||
static_assert(is_embedded<signed int, signed long >::value, "is_embedded"); | |||||
static_assert(is_embedded<signed short, signed long >::value, "is_embedded"); | |||||
static_assert(is_embedded<signed char, signed long >::value, "is_embedded"); | |||||
static_assert(is_embedded<signed short, signed int >::value, "is_embedded"); | |||||
static_assert(is_embedded<signed char, signed int >::value, "is_embedded"); | |||||
static_assert(is_embedded<signed char, signed short >::value, "is_embedded"); | |||||
static_assert(is_embedded<unsigned long, unsigned long long>::value, "is_embedded"); | |||||
static_assert(is_embedded<unsigned int, unsigned long long>::value, "is_embedded"); | |||||
static_assert(is_embedded<unsigned short, unsigned long long>::value, "is_embedded"); | |||||
static_assert(is_embedded<unsigned char, unsigned long long>::value, "is_embedded"); | |||||
static_assert(is_embedded<unsigned int, unsigned long >::value, "is_embedded"); | |||||
static_assert(is_embedded<unsigned short, unsigned long >::value, "is_embedded"); | |||||
static_assert(is_embedded<unsigned char, unsigned long >::value, "is_embedded"); | |||||
static_assert(is_embedded<unsigned short, unsigned int >::value, "is_embedded"); | |||||
static_assert(is_embedded<unsigned char, unsigned int >::value, "is_embedded"); | |||||
static_assert(is_embedded<unsigned char, unsigned short >::value, "is_embedded"); | |||||
TEST(test_mp_util_to, make) | |||||
{ | |||||
EXPECT_EQ(to<int>(static_cast<uint8_t>(8)), 8); | |||||
} |
@@ -1,9 +0,0 @@ | |||||
#include <cpputils/mp/operations/compare/equal.h> | |||||
using namespace ::utl::mp; | |||||
namespace test_mp_operations_compare_equal | |||||
{ | |||||
static_assert(equal(1, 1), ""); | |||||
static_assert(!equal(1, 2), ""); | |||||
} |
@@ -1,9 +0,0 @@ | |||||
#include <cpputils/mp/operations/compare/less.h> | |||||
using namespace ::utl::mp; | |||||
namespace test_mp_operations_compare_equal | |||||
{ | |||||
static_assert(less(1, 2), ""); | |||||
static_assert(!less(2, 1), ""); | |||||
} |
@@ -1,9 +0,0 @@ | |||||
#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), ""); | |||||
} |
@@ -1,9 +0,0 @@ | |||||
#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), ""); | |||||
} |
@@ -1,9 +0,0 @@ | |||||
#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, ""); | |||||
} |