meta: a draft version of typelist and operations for it

This commit is contained in:
Christos Houtouridis 2019-01-29 16:01:57 +02:00
parent 8fef779a91
commit 533a09625c
2 changed files with 912 additions and 271 deletions

File diff suppressed because it is too large Load Diff

View File

@ -26,12 +26,36 @@ namespace test_meta {
using namespace meta; using namespace meta;
/* /*
* Test integral constant * Types to behave like Fixtures
*/ */
// Test type_of fixture // Test type_of fixture
template<class T> struct TestTypeOf { template<class T> struct TestTypeOf {
using type = T; using type = T;
}; };
template<class T1, class T2> struct MfunBin {
using type = int;
};
template<int a, int b> struct MfunBin_i {
using type = int;
};
template<class T1> struct MfunUn1 {
using type = int;
};
template<class T1> struct MfunUn2 {
using type = int;
};
template <typename T> struct Pred_isInt {
using type = std::is_integral<T>;
};
template <typename T> struct Pred_isVoid {
using type = std::is_void<T>;
};
/*
* Test integral constant
*/
TEST(Tmeta_integral, Integreal_type_) { TEST(Tmeta_integral, Integreal_type_) {
EXPECT_EQ(true, (std::is_same<int, type_<TestTypeOf<int>>>::value)); EXPECT_EQ(true, (std::is_same<int, type_<TestTypeOf<int>>>::value));
} }
@ -146,16 +170,102 @@ namespace test_meta {
/* /*
* Test invoke * Test invoke
*/ */
template<class T1, class T2> struct MetaFunction { using type = int; };
template<typename... Args> struct MetaClass {using apply = int; };
TEST(Tmeta_invoke, Invoke) { TEST(Tmeta_invoke, Invoke) {
//EXPECT_EQ (true, (is_evaluable<MetaFunction, int .long>())); using Q = quote<MfunBin>;
using Qi = quote_i<int, MfunBin_i>;
using Q1 = quote<MfunUn1>;
using Q2 = quote<MfunUn2>;
EXPECT_EQ (true, (std::is_same<int, identity_t<int>>()));
EXPECT_EQ (true, (is_applicable_t<MfunBin, int, long>()));
EXPECT_EQ (false, (is_applicable_t<MfunBin, int>()));
EXPECT_EQ (true, (is_applicable_qt<Q, int, long>()));
EXPECT_EQ (false, (is_applicable_qt<Q, int>()));
EXPECT_EQ (true, (is_applicable_it<int, MfunBin_i, 7, 42>()));
EXPECT_EQ (false, (is_applicable_it<int, MfunBin_i, 42>()));
EXPECT_EQ (true, (std::is_same<defer<MfunBin, int, void>::type, MfunBin<int, void>>()));
EXPECT_EQ (true, (std::is_same<defer<MfunBin, void>::type, nil_>()));
EXPECT_EQ (true, (std::is_same<defer_i<int, MfunBin_i, 7, 42>::type, MfunBin_i<7, 42>>()));
EXPECT_EQ (true, (std::is_same<defer_i<int, MfunBin_i, 7>::type, nil_>()));
EXPECT_EQ (true, (std::is_same<invoke<Q, int>, nil_>()));
EXPECT_EQ (true, (std::is_same<invoke<Q, int, void*>, MfunBin<int, void*>>()));
EXPECT_EQ (true, (std::is_same<invoke<Qi, int_<7>, int_<42>>, MfunBin_i<7, 42>>()));
EXPECT_EQ (true, (std::is_same<invoke<Qi, int_<42>>, nil_>()));
EXPECT_EQ (true, (std::is_same<invoke<compose<Q1, Q2>, int>, MfunUn1<MfunUn2<int>>>()));
EXPECT_EQ (true, (std::is_same<
invoke<compose<Q1, Q2, Qi>, int_<7>, int_<42>>,
MfunUn1<MfunUn2<MfunBin_i<7, 42>>>
>()));
EXPECT_EQ (true, (std::is_same<
invoke<compose<Q1, Q2, Qi>, int_<42>>,
MfunUn1<MfunUn2<nil_>>
>()));
EXPECT_EQ (true, (std::is_same<invoke<bind_front<Q, int>, long>, MfunBin<int, long>>()));
EXPECT_EQ (true, (std::is_same<invoke<bind_back<Q, int>, long>, MfunBin<long, int>>()));
} }
/* /*
* Test typelist * Test typelist
*/ */
template<class T1, class T2> struct F {}; TEST(Tmeta_typelist, Basics) {
TEST(Tmeta_typelist, List_fold) { using l1 = typelist<int, int, int>;
using l2 = typelist<int, void*, int, void*>;
using l3 = typelist<>;
EXPECT_EQ (true, (std::is_same<l1, typelist<int>::times<3>>()));
EXPECT_EQ (true, (std::is_same<l2, typelist<int, void*>::times<2>>()));
EXPECT_EQ (true, (std::is_same<l3, typelist<>::times<3>>()));
EXPECT_EQ (true, (std::is_same<l3, typelist<int>::times<0>>()));
EXPECT_EQ (true, (std::is_same<typelist<short, double>, pair<short, double>>()));
EXPECT_EQ (true, (std::is_same<l1, repeat <int_<3>, int>>()));
EXPECT_EQ (true, (std::is_same<l2, repeat_c <2, int, void*>>()));
EXPECT_EQ (3, size<l1>());
EXPECT_EQ (true, empty<l3>());
// pass typelist to an invocable
EXPECT_EQ (true, (std::is_same<type_<
apply<quote<MfunBin>, typelist<int, long>>
>,
MfunBin<int, long>
>()));
}
TEST(Tmeta_typelist, Element_access) {
using l = typelist<char, void, long, double, short>;
EXPECT_EQ (true, (std::is_same<char, at_c<l, 0>>()));
EXPECT_EQ (true, (std::is_same<long, at_c<l, 2>>()));
EXPECT_EQ (true, (std::is_same<nil_, at_c<l, 5>>()));
EXPECT_EQ (true, (std::is_same<void, at<l, int_<1>>>()));
EXPECT_EQ (true, (std::is_same<char, front<l>>()));
EXPECT_EQ (true, (std::is_same<short, back<l>>()));
}
TEST(Tmeta_typelist, Concat) {
using l1 = typelist<int, long, void>;
using l2 = typelist<void*, int*>;
using l3 = typelist<double, long double, short>;
using l4 = typelist<>;
using conc = typelist<int, long, void, void*, int*, double, long double, short>;
EXPECT_EQ(true, (std::is_same<l4, cat<l4, l4>>()));
EXPECT_EQ(true, (std::is_same<conc, cat<l1, l2, l3, l4>>()));
EXPECT_EQ(true, (std::is_same<conc, cat<l1, l4, l2, l3>>()));
EXPECT_EQ(true, (std::is_same<conc, cat<l4, l1, l2, l3>>()));
}
template<class T1, class T2> struct F {}; // binary invocable
TEST(Tmeta_typelist, Fold) {
struct X1 {}; struct X1 {};
struct X2 {}; struct X2 {};
struct X3 {}; struct X3 {};
@ -168,29 +278,116 @@ namespace test_meta {
EXPECT_EQ(true, (std::is_same<fold<typelist<X1, X2, X3>, void, Q>, F<F<F<void, X1>, X2>, X3>>())); EXPECT_EQ(true, (std::is_same<fold<typelist<X1, X2, X3>, void, Q>, F<F<F<void, X1>, X2>, X3>>()));
EXPECT_EQ(true, (std::is_same<fold<typelist<X1, X2, X3, X4>, void, Q>, F<F<F<F<void, X1>, X2>, X3>, X4>>())); EXPECT_EQ(true, (std::is_same<fold<typelist<X1, X2, X3, X4>, void, Q>, F<F<F<F<void, X1>, X2>, X3>, X4>>()));
//EXPECT_EQ(true, (std::is_same<rev_fold<typelist<>, void, Q>, void>())); EXPECT_EQ(true, (std::is_same<rev_fold<typelist<>, void, Q>, void>()));
EXPECT_EQ(true, (std::is_same<rev_fold<typelist<X1>, void, Q>, F<X1, void>>())); EXPECT_EQ(true, (std::is_same<rev_fold<typelist<X1>, void, Q>, F<X1, void>>()));
EXPECT_EQ(true, (std::is_same<rev_fold<typelist<X1, X2>, void, Q>, F<X1, F<X2, void>>>())); EXPECT_EQ(true, (std::is_same<rev_fold<typelist<X1, X2>, void, Q>, F<X1, F<X2, void>>>()));
EXPECT_EQ(true, (std::is_same<rev_fold<typelist<X1, X2, X3>, void, Q>, F<X1, F<X2, F<X3, void>>>>())); EXPECT_EQ(true, (std::is_same<rev_fold<typelist<X1, X2, X3>, void, Q>, F<X1, F<X2, F<X3, void>>>>()));
EXPECT_EQ(true, (std::is_same<rev_fold<typelist<X1, X2, X3, X4>, void, Q>, F<X1, F<X2, F<X3, F<X4, void>>>>>())); EXPECT_EQ(true, (std::is_same<rev_fold<typelist<X1, X2, X3, X4>, void, Q>, F<X1, F<X2, F<X3, F<X4, void>>>>>()));
} }
TEST(Tmeta_typelist, ListOperations) {
using l1 = typelist<int, short, long>;
using l2 = typelist<>;
using l3 = typelist<float, double, long double>;
using l4 = typelist<void*, char*>;
using conc = typelist<int, short, long, float, double, long double, void*, char*>;
using rep = typelist<int, int, int>;
EXPECT_EQ(3, size<l1>()); TEST(Tmeta_typelist, PushPopReverse) {
EXPECT_EQ(true, empty<l2>()); using list = typelist <int, long, void>;
using l_char = typelist <int, long, void, char>;
using l_cc = typelist <int, long, void, char, char>;
using char_l = typelist <char, int, long, void>;
using cc_l = typelist<char, char, int, long, void>;
using rev = typelist<void, long, int>;
EXPECT_EQ(true, (std::is_same<conc, concat<l1, l2, l3, l4>>())); EXPECT_EQ (true, (std::is_same<char_l, push_front<list, char>>()));
EXPECT_EQ(true, (std::is_same<rep, repeat_n<int_<3>, int>>())); EXPECT_EQ (true, (std::is_same<cc_l, push_front<list, char, char>>()));
EXPECT_EQ(true, (std::is_same<int, front<l1>>())); EXPECT_EQ (true, (std::is_same<list, pop_front <char_l>>()));
EXPECT_EQ(true, (std::is_same<long, back<l1>>())); EXPECT_EQ (true, (std::is_same<l_char, push_back <list, char>>()));
EXPECT_EQ(true, (std::is_same<double, at<l3, int_<1>>>())); EXPECT_EQ (true, (std::is_same<l_cc, push_back <list, char, char>>()));
EXPECT_EQ (true, (std::is_same<list, pop_back <l_char>>()));
EXPECT_EQ(true, (std::is_same<typelist<short, long>, pop_front<l1>>())); EXPECT_EQ (true, (std::is_same<rev, reverse <list>>()));
} }
TEST(Tmeta_typelist, Transform) {
using QBin = quote<MfunBin>;
using QUn = quote<MfunUn1>;
using l1 = typelist<char, int, float>;
using l2 = typelist<void, void, void>;
using r = typelist<int, int, int>;
using r_ulazy = typelist <MfunUn1<char>, MfunUn1<int>, MfunUn1<float>>;
using r_blazy = typelist <MfunBin<char, void>, MfunBin<int, void>, MfunBin<float, void>>;
EXPECT_EQ (true, (std::is_same<r, transform<l1, QUn>>()));
EXPECT_EQ (true, (std::is_same<r, transform<l1, l2, QBin>>()));
EXPECT_EQ (true, (std::is_same<r_ulazy, transform_lazy<l1, QUn>>()));
EXPECT_EQ (true, (std::is_same<r_blazy, transform_lazy<l1, l2, QBin>>()));
}
TEST(Tmeta_typelist, Find) {
using l1 = typelist <int, char, long, float>;
using l2 = typelist <char, long, float>;
using l3 = typelist <long, float>;
using empty = typelist<>;
EXPECT_EQ(true, (std::is_same<index_t_<1>, find_if<l1, same_as<char>>>()));
EXPECT_EQ(true, (std::is_same<Npos, find_if<empty, same_as<char>>>()));
EXPECT_EQ(true, (std::is_same<Npos, find_if<l1, same_as<double>>>()));
EXPECT_EQ(true, (std::is_same<index_t_<2>, find<l1, long>>()));
EXPECT_EQ(true, (std::is_same<l2, seek_if<l1, same_as<char>>>()));
EXPECT_EQ(true, (std::is_same<empty, seek_if<empty, same_as<char>>>()));
EXPECT_EQ(true, (std::is_same<empty, seek_if<l1, same_as<double>>>()));
EXPECT_EQ(true, (std::is_same<l3, seek<l1, long>>()));
}
TEST(Tmeta_typelist, Count) {
using list = typelist<int, void*, char, int, long*, char, int, short>;
using empty = typelist<>;
EXPECT_EQ (true, (std::is_same<size_t_<3>, count_if<list, same_as<int>>>()));
EXPECT_EQ (true, (std::is_same<size_t_<2>, count_if<list, same_as<char>>>()));
EXPECT_EQ (true, (std::is_same<size_t_<0>, count_if<list, same_as<double>>>()));
EXPECT_EQ (true, (std::is_same<size_t_<0>, count_if<empty, int>>()));
EXPECT_EQ (true, (std::is_same<size_t_<1>, count<list, void*>>()));
}
TEST(Tmeta_typelist, Filter) {
using Q1 = quote<Pred_isInt>;
using Q2 = quote<Pred_isVoid>;
using list = typelist<int, float, char, long*, short, double, void*>;
using filtered = typelist<int, char, short>;
EXPECT_EQ (true, (std::is_same<filtered, filter<list, Q1>>()));
EXPECT_EQ (true, (std::is_same<typelist<>, filter<typelist<>, Q1>>()));
EXPECT_EQ (true, (std::is_same<typelist<>, filter<list, Q2>>()));
}
TEST(Tmeta_typelist, Replace) {
using Q = quote<Pred_isInt>;
using list = typelist<int, float, char, long*, short, double, void*>;
using res = typelist<void,float, void, long*, void, double, void*>;
using repl = typelist<int, float, void, long*, short, double, void*>;
EXPECT_EQ (true, (std::is_same<res, replace_if<list, Q, void>>()));
EXPECT_EQ (true, (std::is_same<typelist<>, replace_if<typelist<>, Q, void>>()));
EXPECT_EQ (true, (std::is_same<res, replace_if<res, Q, void>>()));
EXPECT_EQ (true, (std::is_same<repl, replace<list, char, void>>()));
}
TEST (Tmeta_typelist, AllAnyNone) {
using l1 = typelist<int, float, char, long*, short, double, void*>;
using l2 = typelist<int, char, long, short>;
EXPECT_EQ (true, (std::is_same<false_, all_of<l1, quote<Pred_isInt>>>()));
EXPECT_EQ (true, (std::is_same<true_, all_of<l2, quote<Pred_isInt>>>()));
EXPECT_EQ (true, (std::is_same<true_, any_of<l1, quote<Pred_isInt>>>()));
EXPECT_EQ (true, (std::is_same<false_, any_of<l2, quote<Pred_isVoid>>>()));
EXPECT_EQ (true, (std::is_same<true_, none_of<l1, quote<Pred_isVoid>>>()));
EXPECT_EQ (true, (std::is_same<false_, none_of<l1, quote<Pred_isInt>>>()));
}
} }