/*!
* \file TmetaTypelist.cpp
*
* Copyright (C) 2018 Christos Choutouridis
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation, either version 3
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see .
*
*/
#include
#include
#include
namespace TmetaTypelist {
using namespace utl;
using namespace meta;
/*
* Types to behave like Fixtures
*/
// Test type_of fixture
template struct Identity {
using type = T;
};
template struct MfunBin {
using type = int;
};
template struct MfunBin_i {
using type = int;
};
template struct MfunUn1 {
using type = int;
};
template struct MfunUn2 {
using type = int;
};
template struct Pred_isInt {
using type = std::is_integral;
};
template struct Pred_isVoid {
using type = std::is_void;
};
/*
* Test high order metaFun tools
*/
TEST(TmetaTypelist, Invoke) {
using W = wrap ;
using Wi = wrap_i;
using W1 = wrap;
using W2 = wrap;
using Q = quote;
using Qi = quote_i;
using Q1 = quote;
using Q2 = quote;
// identity
EXPECT_EQ (true, (std::is_same>>()));
EXPECT_EQ (true, (std::is_same>()));
EXPECT_EQ (true, (std::is_same>()));
// invoke, check that invoke un-wraps and un-quotes staff
EXPECT_EQ (true, (std::is_same< invoke, int, char>, MfunBin >()));
EXPECT_EQ (true, (std::is_same< invoke, int, char>, MfunBin >()));
EXPECT_EQ (true, (std::is_same< invoke, int_<7>, int_<42>>, MfunBin_i<7, 42> >()));
EXPECT_EQ (true, (std::is_same< invoke, int_<7>, int_<42>>, MfunBin_i<7, 42> >()));
// Wrap
EXPECT_EQ (true, (std::is_same< wrap::template apply, MfunBin >()));
EXPECT_EQ (false, (std::is_same< wrap::template apply, MfunBin >()));
EXPECT_EQ (true, (std::is_same< wrap_i::template apply, int_<42>>, MfunBin_i<7, 42> >()));
EXPECT_EQ (false, (std::is_same< wrap_i::template apply, int_<42>>, MfunBin_i<42, 7> >()));
// applicable trait
EXPECT_EQ (true, (is_applicable_t()));
EXPECT_EQ (false, (is_applicable_t()));
EXPECT_EQ (true, (is_applicable_qt()));
EXPECT_EQ (false, (is_applicable_qt()));
EXPECT_EQ (true, (is_applicable_qt()));
EXPECT_EQ (false, (is_applicable_qt()));
EXPECT_EQ (true, (is_applicable_it()));
EXPECT_EQ (false, (is_applicable_it()));
// defer
EXPECT_EQ (true, (std::is_same::type, MfunBin>()));
EXPECT_EQ (true, (std::is_same::type, nil_>()));
EXPECT_EQ (true, (std::is_same::type, MfunBin_i<7, 42>>()));
EXPECT_EQ (true, (std::is_same::type, nil_>()));
// quote
EXPECT_EQ (true, (std::is_same< quote::template apply, MfunBin >()));
EXPECT_EQ (false,(std::is_same< quote::template apply, MfunBin >()));
EXPECT_EQ (true, (std::is_same< quote_i::template apply< int_<7>, int_<42>>, MfunBin_i<7, 42> >()));
EXPECT_EQ (false,(std::is_same< quote_i::template apply< int_<7>, int_<42>>, MfunBin_i<42, 7> >()));
// compose
EXPECT_EQ (true, (std::is_same, int>, MfunUn1>()));
EXPECT_EQ (true, (std::is_same, int>, MfunUn1>>()));
EXPECT_EQ (true, (std::is_same, int>, MfunUn1>()));
EXPECT_EQ (true, (std::is_same, int>, MfunUn1>>()));
EXPECT_EQ (true, (std::is_same<
invoke, int_<7>, int_<42>>, MfunUn1>>
>()));
EXPECT_EQ (true, (std::is_same, int>, MfunUn1>()));
EXPECT_EQ (true, (std::is_same, int>, MfunUn1>>()));
EXPECT_EQ (true, (std::is_same<
invoke, int_<7>, int_<42>>, MfunUn1>>
>()));
// bind
EXPECT_EQ (true, (std::is_same, long>, MfunBin>()));
EXPECT_EQ (true, (std::is_same, long>, MfunBin>()));
// Check the case of ill formed parameter composition. Quote must save us
EXPECT_EQ (true, (std::is_same< nil_, invoke >()));
EXPECT_EQ (true, (std::is_same< nil_, invoke> >()));
EXPECT_EQ (true, (std::is_same< MfunUn1>, invoke, int_<42>> >()));
}
/*
* Test typelist
*/
TEST(TmetaTypelist, Basics) {
using l1 = typelist;
using l2 = typelist;
using l3 = typelist<>;
EXPECT_EQ (true, (std::is_same::times<3>>()));
EXPECT_EQ (true, (std::is_same::times<2>>()));
EXPECT_EQ (true, (std::is_same::times<3>>()));
EXPECT_EQ (true, (std::is_same::times<0>>()));
EXPECT_EQ (true, (std::is_same::times<0>>()));
EXPECT_EQ (true, (std::is_same, pair>()));
EXPECT_EQ (true, (std::is_same, int>>()));
EXPECT_EQ (true, (std::is_same>()));
EXPECT_EQ (3U, size());
EXPECT_EQ (0U, size());
EXPECT_EQ (true, empty());
// pass typelist to an invocable
EXPECT_EQ (true, (std::is_same< apply_t, typelist>, MfunUn1 >()));
EXPECT_EQ (true, (std::is_same< apply_t, typelist>, MfunBin >()));
}
TEST(TmetaTypelist, ElementAccess) {
using l = typelist;
EXPECT_EQ (true, (std::is_same>()));
EXPECT_EQ (true, (std::is_same>()));
EXPECT_EQ (true, (std::is_same>()));
EXPECT_EQ (true, (std::is_same>()));
EXPECT_EQ (true, (std::is_same>>()));
EXPECT_EQ (true, (std::is_same>>()));
EXPECT_EQ (true, (std::is_same>()));
EXPECT_EQ (true, (std::is_same>()));
}
TEST(TmetaTypelist, Concat) {
using l1 = typelist;
using l2 = typelist;
using l3 = typelist;
using l4 = typelist<>;
using conc = typelist;
EXPECT_EQ(true, (std::is_same>()));
EXPECT_EQ(true, (std::is_same>()));
EXPECT_EQ(true, (std::is_same>()));
EXPECT_EQ(true, (std::is_same>()));
}
template struct F {}; // binary invocable
TEST(TmetaTypelist, Fold) {
struct X1 {};
struct X2 {};
struct X3 {};
struct X4 {};
using Q = quote;
EXPECT_EQ(true, (std::is_same, void, Q>, void>()));
EXPECT_EQ(true, (std::is_same, void, Q>, F>()));
EXPECT_EQ(true, (std::is_same, void, Q>, F, X2>>()));
EXPECT_EQ(true, (std::is_same, void, Q>, F, X2>, X3>>()));
EXPECT_EQ(true, (std::is_same, void, Q>, F, X2>, X3>, X4>>()));
EXPECT_EQ(true, (std::is_same, void, Q>, void>()));
EXPECT_EQ(true, (std::is_same, void, Q>, F>()));
EXPECT_EQ(true, (std::is_same, void, Q>, F>>()));
EXPECT_EQ(true, (std::is_same, void, Q>, F>>>()));
EXPECT_EQ(true, (std::is_same, void, Q>, F>>>>()));
}
TEST(TmetaTypelist, PushPopReverse) {
using list = typelist ;
using l_char = typelist ;
using l_cc = typelist ;
using char_l = typelist ;
using cc_l = typelist;
using rev = typelist;
EXPECT_EQ (true, (std::is_same< char_l, push_front >()));
EXPECT_EQ (true, (std::is_same< cc_l, push_front >()));
EXPECT_EQ (true, (std::is_same< list, pop_front >()));
EXPECT_EQ (true, (std::is_same< l_char, push_back >()));
EXPECT_EQ (true, (std::is_same< l_cc, push_back >()));
EXPECT_EQ (true, (std::is_same< list, pop_back >()));
EXPECT_EQ (true, (std::is_same< rev, reverse >()));
}
TEST(TmetaTypelist, Transform) {
using QBin = quote; // both metafuctions return int
using QUn = quote;
using l1 = typelist;
using l2 = typelist;
using r = typelist;
using r_ulazy = typelist , MfunUn1, MfunUn1>;
using r_blazy = typelist , MfunBin, MfunBin>;
EXPECT_EQ (true, (std::is_same>()));
EXPECT_EQ (true, (std::is_same>()));
EXPECT_EQ (true, (std::is_same>()));
EXPECT_EQ (true, (std::is_same>()));
}
TEST(TmetaTypelist, Find) {
using l1 = typelist ;
using l2 = typelist ;
using l3 = typelist ;
using empty = typelist<>;
EXPECT_EQ(true, (std::is_same, find_if>>()));
EXPECT_EQ(true, (std::is_same>>()));
EXPECT_EQ(true, (std::is_same>>()));
EXPECT_EQ(true, (std::is_same, find>()));
EXPECT_EQ(true, (std::is_same>>()));
EXPECT_EQ(true, (std::is_same>>()));
EXPECT_EQ(true, (std::is_same>>()));
EXPECT_EQ(true, (std::is_same>()));
}
TEST(TmetaTypelist, Count) {
using list = typelist;
using empty = typelist<>;
EXPECT_EQ (true, (std::is_same, count_if>>()));
EXPECT_EQ (true, (std::is_same, count_if>>()));
EXPECT_EQ (true, (std::is_same, count_if>>()));
EXPECT_EQ (true, (std::is_same, count_if>()));
EXPECT_EQ (true, (std::is_same, count>()));
}
TEST(TmetaTypelist, Filter) {
using Q1 = quote;
using Q2 = quote;
using list = typelist;
using filtered = typelist;
EXPECT_EQ (true, (std::is_same>()));
EXPECT_EQ (true, (std::is_same, filter, Q1>>()));
EXPECT_EQ (true, (std::is_same, filter>()));
EXPECT_EQ (true, (std::is_same, filter, Q1>>()));
}
TEST(TmetaTypelist, Replace) {
using Q = quote;
using list = typelist;
using res = typelist;
using repl = typelist;
EXPECT_EQ (true, (std::is_same>()));
EXPECT_EQ (true, (std::is_same, replace_if, Q, void>>()));
EXPECT_EQ (true, (std::is_same>()));
EXPECT_EQ (true, (std::is_same, replace_if, Q, void>>()));
EXPECT_EQ (true, (std::is_same>()));
EXPECT_EQ (true, (std::is_same, replace, char, void>>()));
}
TEST (TmetaTypelist, AllAnyNone) {
using l1 = typelist;
using l2 = typelist;
using l3 = typelist<>;
EXPECT_EQ (true, (std::is_same>>()));
EXPECT_EQ (true, (std::is_same>>()));
EXPECT_EQ (true, (std::is_same>>()));
EXPECT_EQ (true, (std::is_same>>()));
EXPECT_EQ (true, (std::is_same>>()));
EXPECT_EQ (true, (std::is_same>>()));
EXPECT_EQ (true, (std::is_same>>()));
EXPECT_EQ (true, (std::is_same>>()));
EXPECT_EQ (true, (std::is_same>>()));
}
}