C++typelist与valuelist实现与验证

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");

}

}
相关推荐
xlq223224 小时前
15.list(上)
数据结构·c++·list
Elias不吃糖4 小时前
总结我的小项目里现在用到的Redis
c++·redis·学习
AA陈超5 小时前
使用UnrealEngine引擎,实现鼠标点击移动
c++·笔记·学习·ue5·虚幻引擎
No0d1es5 小时前
电子学会青少年软件编程(C/C++)六级等级考试真题试卷(2025年9月)
c语言·c++·算法·青少年编程·图形化编程·六级
不会c嘎嘎6 小时前
每日一练 -- day1
c++·算法
yy_xzz6 小时前
VCPKG && Tesseract OCR
c++·图像处理·opencv
hansang_IR7 小时前
【记录】网络流最小割建模三题
c++·算法·网络流·最小割
玖笙&7 小时前
✨WPF编程进阶【7.3】集成动画(附源码)
c++·c#·wpf·visual studio
Dream it possible!7 小时前
LeetCode 面试经典 150_二叉树层次遍历_二叉树的层序遍历(83_102_C++_中等)
c++·leetcode·面试·二叉树
AA陈超7 小时前
Lyra源码分析:LyraCharacterMovementComponent
c++·笔记·学习·ue5·虚幻引擎·lyra