cpp
//hpp
#pragma once
#include <type_traits>
template< class T >
struct type_identity {
using type = T;
};
template< class T >
using type_identity_t = typename type_identity<T>::type;
template < typename... Elements>
class Typelist
{
};
template<typename List>
class Front;
template<typename Head, typename... Tail>
class Front <Typelist<Head, Tail...>>
{
public:
using type = Head;
};
template<typename List>
using Front_t = typename Front<List>::type;
/*---------------------*/
template < typename List>
class PopFront;
template <typename Head, typename... Tail>
class PopFront<Typelist<Head, Tail...>> {
public:
using type = Typelist<Tail...>;
};
template < typename List>
using PopFront_t = typename PopFront<List>::type;
/*---------------------*/
template < typename List, typename NewElement>
class PushFront;
template < typename... Elements, typename NewElement>
class PushFront<Typelist<Elements...>, NewElement> {
public:
using type = Typelist<NewElement, Elements...>;
};
template < typename List, typename NewElement>
using PushFront_t = typename PushFront<List, NewElement>::type;
/*---------------------*/
template<typename List, size_t N>
class NthElement : public NthElement <PopFront_t<List>, N - 1>
{
};
// basis case:
template<typename List>
class NthElement<List, 0> : public Front<List>
{
};
template < typename List, size_t N>
using NthElement_t = typename NthElement<List, N>::type;
/*---------------------*/
template <typename List>
class IsEmpty
{
public:
static constexpr bool value = false;
};
template<>
class IsEmpty<Typelist<>> {
public:
static constexpr bool value = true;
};
/*---------------------*/
template < typename List, bool Empty = IsEmpty<List>::value>
class LargestType;
template <typename List>
class LargestType<List, false>
{
private:
using Contender = Front_t<List>;
using Best = typename LargestType<PopFront_t<List>>::type;
public:
using type = std::conditional_t<(sizeof(Contender) >= sizeof(Best)), Contender, Best>;
};
template <typename List>
class LargestType<List, true>
{
public:
using type = char;
};
template < typename List>
using LargestType_t = typename LargestType<List>::type;
/*---------------------*/
template<typename List, typename NewElement, bool = IsEmpty<List>::value>
class PushBack;
template<typename List, typename NewElement>
class PushBack <List, NewElement, false>
{
using Head = Front_t<List>;
using Tail = PopFront_t<List>;
using NewTail = typename PushBack<Tail, NewElement>::type;
public:
using type = PushFront_t<NewTail, Head >;
};
template <typename List, typename NewElement>
class PushBack <List, NewElement, true>
{
public:
using type = PushFront_t<List, NewElement>;
};
//// generic push-back operation:
//template < typename List, typename NewElement>
//class PushBack : public PushBackHelper<List, NewElement> { };
template < typename List, typename NewElement>
using PushBack_t = typename PushBack<List, NewElement>::type;
/*---------------------*/
template < typename List, bool Empty = IsEmpty<List>::value>
class Reverse;
template < typename List>
using Reverse_t = typename Reverse<List>::type;
template<typename List>
class Reverse<List, false>
: public PushBack<Reverse_t<PopFront_t<List>>, Front_t<List>> { };
template <typename List>
class Reverse<List, true>
{
public:
using type = List;
};
/*---------------------*/
template < typename List>
class PopBack {
public:
using type = Reverse_t<PopFront_t<Reverse_t<List>>>;
};
template < typename List>
using PopBack_t = typename PopBack<List>::type;
/*---------------------*/
template<typename List, template<typename T> class MetaFun, bool Empty = IsEmpty<List>::value>
class Transform;
template < typename List, template<typename T> class MetaFun>
using Transform_t = typename Transform<List, MetaFun>::type;
template<typename List, template<typename T> class MetaFun>
class Transform <List, MetaFun, false>
: public PushFront <Transform_t<PopFront_t<List>, MetaFun>, typename MetaFun<Front_t<List>>::type>
{
};
template < typename... Elements, template<typename T> class MetaFun>
class Transform <Typelist<Elements...>, MetaFun, false>
{
public:
using type = Typelist<typename MetaFun<Elements>::type...>;
};
template <typename List, template<typename T> class MetaFun>
class Transform <List, MetaFun, true>
{
public:
using type = List;
};
/*---------------------*/
template < typename List,
template<typename X, typename Y> class F,
typename I,
bool = IsEmpty<List>::value>
class Accumulate;
template < typename List,
template<typename X, typename Y> class F,
typename I>
using Accumulate_t = typename Accumulate<List, F, I>::type;
template<typename List,
template<typename X, typename Y> class F,
typename I>
class Accumulate<List, F, I, false>
: public Accumulate<PopFront_t<List>, F, typename F<I, Front_t<List>>::type>
{
};
template<typename List,
template<typename X, typename Y> class F,
typename I>
class Accumulate<List, F, I, true>
{
public:
using type = I;
};
//meta
template <typename T, typename U>
class MoreCompare
: public std::conditional< sizeof(T) >= sizeof(U), T, U>
{
public:
static constexpr inline bool value = sizeof(T) >= sizeof(U);
};
template<typename T>
struct AddPointer {
using type = T*;
};
/*-----------------------*/
//排序递归
template<typename List,
template<typename T, typename U> class Compare,
bool = IsEmpty<List>::value>
class InsertionSort;
template<typename List,
template<typename T, typename U> class Compare>
using InsertionSort_t = typename InsertionSort<List, Compare>::type;
//插入递归
template < typename List, typename Element,
template<typename T, typename U> class Compare,
bool = IsEmpty<List>::value>
class InsertSorted;
template < typename List, typename Element,
template<typename T, typename U> class Compare>
using InsertSorted_t = typename InsertSorted<List, Element, Compare>::type;
template<typename List,
template<typename T, typename U> class Compare>
class InsertionSort <List, Compare, false>
: public InsertSorted <InsertionSort_t<PopFront_t<List>, Compare>,
Front_t<List>, Compare>
{
};
template<typename List,
template<typename T, typename U> class Compare>
class InsertionSort <List, Compare, true>
{
public:
using type = List;
};
template<typename List, typename Element,
template<typename T, typename U> class Compare>
class InsertSorted<List, Element, Compare, false>
{
using NewTail = std::conditional_t<Compare<Element, Front_t<List>>::value,
type_identity_t<List>,
InsertSorted_t <PopFront_t<List>, Element, Compare>
>;
using NewHead = std::conditional_t<Compare<Element, Front_t<List>>::value,
Element,
Front_t<List>>;
public:
using type = PushFront_t<NewTail, NewHead>;
};
template < typename List, typename Element,
template<typename T, typename U> class Compare>
class InsertSorted<List, Element, Compare, true>
: public PushFront <List, Element>
{
};
/*--------------------------------*/
template<typename T, T Val>
struct CTValue
{
static constexpr auto value = Val;
};
template < typename T, T... Values>
struct Valuelist {
};
template < typename T, T... Values>
struct IsEmpty<Valuelist<T, Values...>> {
static constexpr bool value = sizeof...(Values) == 0;
};
template < typename T, T Head, T... Tail>
struct Front<Valuelist<T, Head, Tail...>> {
using type = CTValue<T, Head>;
static constexpr T value = Head;
};
template < typename T, T Head, T... Tail>
struct PopFront<Valuelist<T, Head, Tail...>> {
using type = Valuelist<T, Tail...>;
};
template < typename T, T... Values, T New>
struct PushFront<Valuelist<T, Values...>, CTValue<T, New>> {
using type = Valuelist<T, New, Values...>;
};
#if _HAS_CXX17
//PushBack的主模板有三个模板形参,一个有默认模板参数
//C++17 以后 主模板的默认模板参数参与偏特化时的模板实参列表的推导动作 PushBack<Valuelist<T, Values...>, CTValue<T, New>>=>相当于声明了 PushBack<Valuelist<T, Values...>, CTValue<T, New>,IsEmpty<Valuelist<T, Values...>>::value>
//且允许偏特化的非类型模板参数是复杂的标识符=>如:IsEmpty<Valuelist<T, Values...>>::value
//主模板的默认模板参数既在实例化时推导并附加【也在声明偏特化模板时进行偏特化实参声明的推导匹配】
template <typename T, T... Values, T New>
struct PushBack<Valuelist<T, Values...>, CTValue<T, New>> {
using type = Valuelist<T, Values..., New>;
};
#else
//C++14 主模板的默认模板参数不参与偏特化时的模板实参列表的推导动作
//偏特化的非类型模板参数必须是简单标识符=>如:false或者true
//主模板的默认模板参数只在实例化时推导并附加【不在声明偏特化模板时进行偏特化实参声明的推导匹配】
template <typename T, T... Values, T New>
struct PushBack<Valuelist<T, Values...>, CTValue<T, New>, false> {
using type = Valuelist<T, Values..., New>;
};
template <typename T, T... Values, T New>
struct PushBack<Valuelist<T, Values...>, CTValue<T, New>, true> {
using type = Valuelist<T, Values..., New>;
};
#endif
template < typename List, typename Indices>
class SelectList;
template<typename List, size_t... Indices>
class SelectList<List, Valuelist<size_t, Indices...>>
{
public:
using type = Typelist<NthElement_t<List, Indices>...>;
};
template<typename Types, typename Indices>
using SelectList_t = typename SelectList<Types, Indices>::type;
测试代码:
cpp
#include <iostream>
#include "Typelist.h" // 你的代码所在的头文件
// 方便写测试
template<typename A, typename B>
constexpr bool same = std::is_same<A, B>::value;
int main()
{
using L0 = Typelist<>;
using L1 = Typelist<int>;
using L3 = Typelist<int, double, char>;
// -----------------------------
// IsEmpty
// -----------------------------
static_assert(IsEmpty<L0>::value == true);
static_assert(IsEmpty<L1>::value == false);
// -----------------------------
// Front
// -----------------------------
static_assert(same<Front_t<L3>, int>);
static_assert(same<Front_t<L1>, int>);
// -----------------------------
// PopFront
// -----------------------------
static_assert(same<PopFront_t<L3>, Typelist<double, char>>);
static_assert(same<PopFront_t<L1>, Typelist<>>);
// -----------------------------
// PushFront
// -----------------------------
static_assert(same<
PushFront_t<L3, long>,
Typelist<long, int, double, char>
>);
// -----------------------------
// NthElement
// -----------------------------
static_assert(same<NthElement_t<L3, 0>, int>);
static_assert(same<NthElement_t<L3, 1>, double>);
static_assert(same<NthElement_t<L3, 2>, char>);
// -----------------------------
// LargestType
// -----------------------------
static_assert(same<LargestType_t<L3>, double>); // double 最大
// -----------------------------
// PushBack
// -----------------------------
static_assert(same<
PushBack_t<L3, long>,
Typelist<int, double, char, long>
>);
// -----------------------------
// Reverse
// -----------------------------
static_assert(same<
Reverse_t<L3>,
Typelist<char, double, int>
>);
// -----------------------------
// PopBack
// -----------------------------
static_assert(same<
PopBack_t<L3>,
Typelist<int, double>
>);
// -----------------------------
// Transform
// -----------------------------
static_assert(same<
Transform_t<Typelist<int, char>, AddPointer>,
Typelist<int*, char*>
>);
// -----------------------------
// Accumulate
// -----------------------------
static_assert(same<
Accumulate_t<L3, MoreCompare, char>,
double // double 最大
>);
// -----------------------------
// InsertionSort
// -----------------------------
using Lunsorted = Typelist<char, long long, int, short>;
using Lsorted = InsertionSort_t<Lunsorted, MoreCompare>;
static_assert(same<
Lsorted,
Typelist<long long, int, short, char>
>);
// 全部测试通过
std::cout << "All typelist tests passed.\n";
/* ---------- Valuelist Test ---------- */
using VL = Valuelist<int, 3, 1, 4, 2>;
static_assert(IsEmpty<VL>::value == false, "VL is not empty");
static_assert(Front<VL>::value == 3, "Front should be 3");
using Popped = PopFront<VL>::type;
static_assert(Front<Popped>::value == 1, "Next should be 1");
using PushedFront = PushFront<VL, CTValue<int, 9>>::type;
static_assert(Front<PushedFront>::value == 9, "Should start from 9");
using PushedBack = PushBack_t<VL, CTValue<int, 8>>;
using ExpectedBack = Valuelist<int, 3, 1, 4, 2, 8>;
static_assert(std::is_same<PushedBack, ExpectedBack>::value, "PushBack failed");
/* ---------- SelectList Test ---------- */
using TL = Typelist<char, short, int, long, float>;
using Indices = Valuelist<size_t, 1, 3, 4>;
using Result = SelectList_t<TL, Indices>;
using Expected = Typelist<short, long, float>;
static_assert(std::is_same<Result, Expected>::value, "SelectList_t failed");
}
}