1
0
forked from boostorg/mp11

🆕 [mp_unique_if] Support for mp_unique with a predicate

Problem:
- `mp_unique` doesn't support custom predicates.

Solution:
- Add `mp_unique_if` and `mp_unique_if_q` which allow to remove duplicates elements with a predicate.
This commit is contained in:
Kris Jusiak
2019-12-03 13:08:32 -07:00
parent f64bc319c0
commit aa11577812
5 changed files with 135 additions and 0 deletions

View File

@@ -659,6 +659,18 @@ As `mp_reverse_fold`, but takes a quoted metafunction.
`mp_unique<L>` returns a list of the same form as `L` with the duplicate elements removed.
## mp_unique_if<L, P>
template<class L> using mp_unique_if = /*...*/;
`mp_unique_if<L, P>` returns a list of the same form as `L` with the duplicate elements removed for which `mp_to_bool<P<T>>` is `mp_true`.
## mp_unique_if<L, Q>
template<class L, class Q> using mp_unique_if = mp_unique_if<L, Q::template fn>;
As `mp_unique_if`, but takes a quoted metafunction.
## mp_all_of<L, P>
template<class L, template<class...> class P> using mp_all_of =

View File

@@ -950,6 +950,22 @@ template<template<class...> class L, class... T> struct mp_unique_impl<L<T...>>
template<class L> using mp_unique = typename detail::mp_unique_impl<L>::type;
namespace detail {
template <template<class...> class P> struct mp_unique_if_push_back {
template<class...> struct impl;
template <template<class...> class L, class... Ts, class T>
struct impl<L<Ts...>, T> {
using type = mp_if<mp_any<P<Ts, T>...>, L<Ts...>, L<Ts..., T>>;
};
template <class... T> using fn = typename impl<T...>::type;
};
} // namespace detail
// mp_unique_if<L, P>
template <class L, template<class...> class P>
using mp_unique_if = mp_fold_q<L, mp_clear<L>, detail::mp_unique_if_push_back<P>>;
template<class L, class Q> using mp_unique_if_q = mp_unique_if<L, Q::template fn>;
// mp_all_of<L, P>
template<class L, template<class...> class P> using mp_all_of = mp_bool< mp_count_if<L, P>::value == mp_size<L>::value >;
template<class L, class Q> using mp_all_of_q = mp_all_of<L, Q::template fn>;

View File

@@ -92,6 +92,8 @@ run mp_fold_q.cpp ;
run mp_reverse_fold.cpp ;
run mp_reverse_fold_q.cpp ;
run mp_unique.cpp ;
run mp_unique_if.cpp ;
run mp_unique_if_q.cpp ;
run mp_all_of.cpp ;
run mp_all_of_q.cpp ;
run mp_any_of.cpp ;

54
test/mp_unique_if.cpp Normal file
View File

@@ -0,0 +1,54 @@
// Copyright 2015 Peter Dimov.
// Copyright 2019 Kris Jusiak.
//
// Distributed under the Boost Software License, Version 1.0.
//
// See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt
#include <boost/mp11/algorithm.hpp>
#include <boost/mp11/list.hpp>
#include <boost/core/lightweight_test_trait.hpp>
#include <type_traits>
#include <tuple>
int main()
{
using boost::mp11::mp_list;
using boost::mp11::mp_unique_if;
{
BOOST_TEST_TRAIT_TRUE((std::is_same<mp_unique_if<mp_list<>, std::is_same>,mp_list<>>));
BOOST_TEST_TRAIT_TRUE((std::is_same<mp_unique_if<mp_list<void>, std::is_same>,mp_list<void>>));
BOOST_TEST_TRAIT_TRUE((std::is_same<mp_unique_if<mp_list<void, void>, std::is_same>,mp_list<void>>));
BOOST_TEST_TRAIT_TRUE((std::is_same<mp_unique_if<mp_list<void, void, void>, std::is_same>,mp_list<void>>));
BOOST_TEST_TRAIT_TRUE((std::is_same<mp_unique_if<mp_list<void, void, void, void>, std::is_same>,mp_list<void>>));
BOOST_TEST_TRAIT_TRUE((std::is_same<mp_unique_if<mp_list<void, int>, std::is_same>,mp_list<void, int>>));
BOOST_TEST_TRAIT_TRUE((std::is_same<mp_unique_if<mp_list<void, void, void, int, int, int>, std::is_same>,mp_list<void, int>>));
BOOST_TEST_TRAIT_TRUE((std::is_same<mp_unique_if<mp_list<void, int, void, int, int, void, int, int, int>, std::is_same>,mp_list<void, int>>));
BOOST_TEST_TRAIT_TRUE((std::is_same<mp_unique_if<mp_list<void, int, char[]>, std::is_same>,mp_list<void, int, char[]>>));
BOOST_TEST_TRAIT_TRUE((std::is_same<mp_unique_if<mp_list<void, int, char[], void, int, char[], void, int, char[]>, std::is_same>,mp_list<void, int, char[]>>));
}
{
BOOST_TEST_TRAIT_TRUE((std::is_same<mp_unique_if<std::tuple<>, std::is_same>,std::tuple<>>));
BOOST_TEST_TRAIT_TRUE((std::is_same<mp_unique_if<std::tuple<void>, std::is_same>,std::tuple<void>>));
BOOST_TEST_TRAIT_TRUE((std::is_same<mp_unique_if<std::tuple<void, void>, std::is_same>,std::tuple<void>>));
BOOST_TEST_TRAIT_TRUE((std::is_same<mp_unique_if<std::tuple<void, void, void>, std::is_same>,std::tuple<void>>));
BOOST_TEST_TRAIT_TRUE((std::is_same<mp_unique_if<std::tuple<void, void, void, void>, std::is_same>,std::tuple<void>>));
BOOST_TEST_TRAIT_TRUE((std::is_same<mp_unique_if<std::tuple<void, int>, std::is_same>,std::tuple<void, int>>));
BOOST_TEST_TRAIT_TRUE((std::is_same<mp_unique_if<std::tuple<void, void, void, int, int, int>, std::is_same>,std::tuple<void, int>>));
BOOST_TEST_TRAIT_TRUE((std::is_same<mp_unique_if<std::tuple<void, int, void, int, int, void, int, int, int>, std::is_same>,std::tuple<void, int>>));
BOOST_TEST_TRAIT_TRUE((std::is_same<mp_unique_if<std::tuple<void, int, char[]>, std::is_same>,std::tuple<void, int, char[]>>));
BOOST_TEST_TRAIT_TRUE((std::is_same<mp_unique_if<std::tuple<void, int, char[], void, int, char[], void, int, char[]>, std::is_same>,std::tuple<void, int, char[]>>));
}
return boost::report_errors();
}

51
test/mp_unique_if_q.cpp Normal file
View File

@@ -0,0 +1,51 @@
// Copyright 2015 Peter Dimov.
// Copyright 2019 Kris Jusiak.
//
// Distributed under the Boost Software License, Version 1.0.
//
// See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt
#include <boost/mp11/algorithm.hpp>
#include <boost/mp11/list.hpp>
#include <boost/core/lightweight_test_trait.hpp>
#include <type_traits>
#include <tuple>
struct is_same_size
{
template<class TLhs, class TRhs>
struct impl : boost::mp11::mp_bool<sizeof(TLhs) == sizeof(TRhs)> {};
template<class TLhs, class TRhs> using fn = typename impl<TLhs, TRhs>::type;
};
int main()
{
using boost::mp11::mp_list;
using boost::mp11::mp_unique_if_q;
{
BOOST_TEST_TRAIT_TRUE((std::is_same<mp_unique_if_q<mp_list<>, is_same_size>, mp_list<>>));
BOOST_TEST_TRAIT_TRUE((std::is_same<mp_unique_if_q<mp_list<int>, is_same_size>, mp_list<int>>));
BOOST_TEST_TRAIT_TRUE((std::is_same<mp_unique_if_q<mp_list<int, int>, is_same_size>, mp_list<int>>));
BOOST_TEST_TRAIT_TRUE((std::is_same<mp_unique_if_q<mp_list<char, bool>, is_same_size>, mp_list<char>>));
BOOST_TEST_TRAIT_TRUE((std::is_same<mp_unique_if_q<mp_list<bool, char>, is_same_size>, mp_list<bool>>));
BOOST_TEST_TRAIT_TRUE((std::is_same<mp_unique_if_q<mp_list<bool, char, bool>, is_same_size>, mp_list<bool>>));
struct foo{};
BOOST_TEST_TRAIT_TRUE((std::is_same<mp_unique_if_q<mp_list<char, bool, int, foo>, is_same_size>, mp_list<char, int>>));
}
{
BOOST_TEST_TRAIT_TRUE((std::is_same<mp_unique_if_q<std::tuple<>, is_same_size>, std::tuple<>>));
BOOST_TEST_TRAIT_TRUE((std::is_same<mp_unique_if_q<std::tuple<int>, is_same_size>, std::tuple<int>>));
BOOST_TEST_TRAIT_TRUE((std::is_same<mp_unique_if_q<std::tuple<int, int>, is_same_size>, std::tuple<int>>));
BOOST_TEST_TRAIT_TRUE((std::is_same<mp_unique_if_q<std::tuple<char, bool>, is_same_size>, std::tuple<char>>));
BOOST_TEST_TRAIT_TRUE((std::is_same<mp_unique_if_q<std::tuple<bool, char>, is_same_size>, std::tuple<bool>>));
BOOST_TEST_TRAIT_TRUE((std::is_same<mp_unique_if_q<std::tuple<bool, char, bool>, is_same_size>, std::tuple<bool>>));
struct foo{};
BOOST_TEST_TRAIT_TRUE((std::is_same<mp_unique_if_q<std::tuple<char, bool, int, foo>, is_same_size>, std::tuple<char, int>>));
}
return boost::report_errors();
}