tmp/tests/packalgo.cpp

150 lines
4.2 KiB
C++

#include "catch_tmp.h"
#include <algorithm.h>
using namespace tmp;
namespace {
template<unsigned N = 0> struct UInt { static constexpr unsigned value = N; };
template<typename T> struct IdentityImpl { using type = T; };
template<typename T> using Identity = typename IdentityImpl<T>::type;
template<typename> struct UnpackImpl;
template<typename T> struct UnpackImpl<Pack<T>> { using type = T; };
template<typename T> using Unpack = typename UnpackImpl<T>::type;
template<typename T> struct SizeofImpl { using type = UInt<sizeof(T)>; };
template<typename T> using Sizeof = typename SizeofImpl<T>::type;
template<typename P0, typename P1> using Merge = PackCat<P0, P1>;
template<typename U0, typename U1> struct USumImpl { using type = UInt<U0::value+U1::value>; };
template<typename U0, typename U1> using USum = typename USumImpl<U0, U1>::type;
template<typename T> struct IsEven: std::integral_constant<bool, not(T::value & 1)> {};
}
TEST_CASE("Transform") {
SECTION("empty input") {
using Result = Transform<Pack<>, Identity>;
REQUIRE_SAME(Pack<>, Result);
}
using Input0 = Pack<Pack<char>, Pack<float>, Pack<int>>;
using Input1 = Pack<bool, char, short, int, long, long long>;
SECTION("Identity") {
REQUIRE(std::is_same<Input0, Transform<Input0, Identity>>{});
REQUIRE(std::is_same<Input1, Transform<Input1, Identity>>{});
}
SECTION("Unpack") {
using Expected = Pack<char, float, int>;
using Result = Transform<Input0, Unpack>;
REQUIRE_SAME(Expected, Result);
}
SECTION("Sizeof") {
using Expected = Pack<UInt<sizeof(bool)>, UInt<sizeof(char)>, UInt<sizeof(short)>, UInt<sizeof(int)>, UInt<sizeof(long)>, UInt<sizeof(long long)>>;
using Result = Transform<Input1, Sizeof>;
REQUIRE_SAME(Expected, Result);
}
}
TEST_CASE("Accumulate") {
SECTION("empty input") {
using Result = Accumulate<Pack<>, PackCat, void>;
REQUIRE_SAME(void, Result);
}
using Input0 = Pack<Pack<char>, Pack<float>, Pack<int>>;
using Input1 = Pack<bool, char, short, int, long, long long>;
SECTION("PackCat") {
using Expected = Pack<char, float, int>;
using Result = Accumulate<Input0, PackCat, Pack<>>;
REQUIRE_SAME(Expected, Result);
}
SECTION("USum") {
using Expected = UInt<sizeof(bool)+sizeof(char)+sizeof(short)+sizeof(int)+sizeof(long)+sizeof(long long)>;
using Result = Accumulate<Transform<Input1, Sizeof>, USum, UInt<>>;
REQUIRE_SAME(Expected, Result);
}
}
TEST_CASE("Filter") {
SECTION("empty input") {
using Expected = Pack<>;
using Result = Filter<Pack<>, IsEven>;
REQUIRE_SAME(Expected, Result);
}
SECTION("empty output") {
using Input = Pack<UInt<1>, UInt<3>, UInt<3>, UInt<5>, UInt<5>, UInt<7>>;
using Expected = Pack<>;
using Result = Filter<Input, IsEven>;
REQUIRE_SAME(Expected, Result);
}
SECTION("general case") {
using Input = Pack<UInt<1>, UInt<2>, UInt<3>, UInt<4>, UInt<5>, UInt<6>>;
using Expected = Pack<UInt<2>, UInt<4>, UInt<6>>;
using Result = Filter<Input, IsEven>;
REQUIRE_SAME(Expected, Result);
}
}
TEST_CASE("Cut") {
SECTION("empty input") {
using Expected = Pack<Pack<>, Pack<>>;
using Result = Cut<Pack<>, IsEven>;
REQUIRE_SAME(Expected, Result);
}
SECTION("empty left output") {
using Input = Pack<UInt<1>, UInt<3>, UInt<3>, UInt<5>, UInt<5>, UInt<7>>;
using Expected = Pack<Pack<>, Input>;
using Result = Cut<Input, IsEven>;
REQUIRE_SAME(Expected, Result);
}
SECTION("empty right output") {
using Input = Pack<UInt<2>, UInt<4>, UInt<4>, UInt<6>, UInt<6>, UInt<8>>;
using Expected = Pack<Input, Pack<>>;
using Result = Cut<Input, IsEven>;
REQUIRE_SAME(Expected, Result);
}
SECTION("general case") {
using Input = Pack<UInt<2>, UInt<2>, UInt<3>, UInt<3>, UInt<5>, UInt<7>>;
using Expected = Pack<Pack<UInt<2>, UInt<2>>, Pack<UInt<3>, UInt<3>, UInt<5>, UInt<7>>>;
using Result = Cut<Input, IsEven>;
REQUIRE_SAME(Expected, Result);
}
}
TEST_CASE("Reverse") {
SECTION("empty input") {
REQUIRE_SAME(Pack<>, Reverse<Pack<>>);
}
SECTION("one element") {
REQUIRE_SAME(Pack<void>, Reverse<Pack<void>>);
}
SECTION("general case") {
using Input = Pack<bool, char, short, int, long>;
using Expected = Pack<long, int, short, char, bool>;
using Result = Reverse<Input>;
REQUIRE_SAME(Expected, Result);
}
}