C++ 模板元编程 笔记

发布时间 2023-12-26 23:28:26作者: SovietPower


很有意思但不知道实际有啥用的东西

链表

#include <iostream>
#include <type_traits>

/*
功能:
- 获取 size
- 将 List 从指定位置拆分成两个
- 合并两个 List
- 读取/删除某位置的元素
- 在头部/末尾/任意位置插入元素
- 查询某元素第一次出现的位置
(修改指定位置的值,可以通过删除+插入实现,懒得再封装了)

可以支持任意类型而不是 int,再加一个模板参数 T 即可。
*/
template <int... values>
struct List;

template <>
struct List<> {
	static constexpr size_t size = 0;
};
using EmptyList = List<>;

template <int head, int... values>
struct List<head, values...> {
	static constexpr int front = head;
	static constexpr size_t size = 1 + sizeof...(values);
	using PopFrontT = std::conditional_t<size == 1, EmptyList, List<values...>>;
};

// template <int head>
// struct List<head> { // 长度为 1 的情况
// 	static constexpr int front = head;
// 	static constexpr size_t size = 1;
// 	using PopFrontT = EmptyList;
// };

// --- insert
template <typename T, int value>
struct PushFront;

template <int... values, int x>
struct PushFront<List<values...>, x> {
	using type = List<x, values...>;
};

template <typename T, int value>
struct PushBack;

template <int... values, int x>
struct PushBack<List<values...>, x> {
	using type = List<values..., x>;
};

// --- split:将 List 从指定位置拆分成两个
template <size_t pos, typename L, typename R>
struct SplitImpl;

template <size_t now, int... L, int... R>
struct SplitImpl<now, List<L...>, List<R...>> { // 每次取出 R 中的一个放入 L
	using next = SplitImpl<now - 1, List<L..., List<R...>::front>, typename List<R...>::PopFrontT>;
	using newL = typename next::newL;
	using newR = typename next::newR;
};

template <int... L, int... R>
struct SplitImpl<0, List<L...>, List<R...>> {
	using newL = List<L...>;
	using newR = List<R...>;
};

template <size_t pos, typename T>
struct Split;

template <size_t pos, int... values>
struct Split<pos, List<values...>> {
	using L = typename SplitImpl<pos, EmptyList, List<values...>>::newL;
	using R = typename SplitImpl<pos, EmptyList, List<values...>>::newR;
};

// --- merge:合并两个 List
template <typename L, typename R>
struct Merge;

template <int... L, int... R>
struct Merge<List<L...>, List<R...>> {
	using type = List<L..., R...>;
};

// --- get:读取某位置的元素
template <size_t pos, typename T>
struct Get;

template <size_t pos, int... values>
struct Get<pos, List<values...>> {
	static constexpr int value = Get<pos - 1, typename List<values...>::PopFrontT>::value;
};

template <int... values>
struct Get<0, List<values...>> {
	static constexpr int value = List<values...>::front;
};

// --- delete:删除某位置的元素
template <size_t pos, typename T>
struct Delete;

template <size_t pos, int... values>
struct Delete<pos, List<values...>> {
	using temp = Split<pos, List<values...>>;
	using type = typename Merge<typename temp::L, typename temp::R::PopFrontT>::type;
};

// --- insert:在某位置插入元素
template <size_t pos, int x, typename T>
struct Insert;

template <size_t pos, int x, int... values>
struct Insert<pos, x, List<values...>> {
	using temp = Split<pos, List<values...>>;
	using type = typename Merge<typename PushBack<typename temp::L, x>::type, typename temp::R>::type;
};

// --- find:查询某元素第一次出现的位置
template <typename T, int v, int now>
struct FindImpl;

template <int v, int front, int... values, int now>
struct FindImpl<List<front, values...>, v, now> {
	static constexpr int pos = v == front ? now : FindImpl<List<values...>, v, now + 1>::pos;
};

template <int v, int now>
struct FindImpl<List<>, v, now> {
	static constexpr int pos = -1;
};

template <typename T, auto value>
struct Find;

template <int v, int... values>
struct Find<List<values...>, v>: FindImpl<List<values...>, v, 0> {};

// ---

int main() {
	using L1 = List<1, 2, 3, 4>;
	using L1l = Split<2, L1>::L;
	using L2 = List<3, 4, 5>;
	using L1l2 = Merge<L1l, L2>::type;
	using L2pf = PushFront<L2, 2>::type;
	using L2pfpb = PushBack<L2pf, 6>::type;

	using L2d1 = Delete<0, L2pfpb>::type;
	using L2d2 = Delete<2, L2pfpb>::type;
	using L2d3 = Delete<4, L2pfpb>::type;

	using L3i1 = Insert<0, 0, L1>::type;
	using L3i2 = Insert<2, 0, L1>::type;
	using L3i3 = Insert<4, 0, L1>::type;

	[](...) {} (
		EmptyList::size,
		L1::size,

		Get<0, L1>::value,
		Get<3, L1>::value,
		// Get<4, L1>::value, // 可以在编译期检查越界(因为没有该模板的定义)

		Find<L1, 1>::pos,
		Find<L1, 3>::pos,
		Find<L1, 4>::pos,
		Find<L1, 5>::pos
	);
}

数组

#include <cstdio>
#include <vector>
#include <iostream>
#include <type_traits>

/*
功能:
- 获取 size
- 拆分一个数组
- 合并两个数组
- 读写某位置的元素
- 在任意位置插入元素

支持任意类型(只能有一种)。
实现与链表类似,只是有数组后可直接获取某位置的元素。
*/

template<typename T, T... values>
struct Array;

template<typename T, T head, T... values>
struct Array<T, head, values...> {
	using ValueType = T;
	static constexpr size_t size = 1 + sizeof...(values);
	static constexpr T front = head;
	static constexpr T data[] = {head, values...};
	using PopFrontT = Array<T, values...>;

	static_assert(size > 0);
};

template<typename T>
struct Array<T> {
	using ValueType = T;
	static constexpr size_t size = 0;
};

template<typename T>
using EmptyArray = Array<T>;

// split
template <size_t pos, typename L, typename R>
struct SplitImpl;

template <size_t now, typename T, T... L, T... R>
struct SplitImpl<now, Array<T, L...>, Array<T, R...>> {
	using next = SplitImpl<now - 1, Array<T, L..., Array<T, R...>::front>, typename Array<T, R...>::PopFrontT>;
	using newL = typename next::newL;
	using newR = typename next::newR;
};

template <typename T, T... L, T... R>
struct SplitImpl<0, Array<T, L...>, Array<T, R...>> {
	using newL = Array<T, L...>;
	using newR = Array<T, R...>;
};

template <size_t pos, typename T>
struct Split;

template <size_t pos, typename T, int... values>
struct Split<pos, Array<T, values...>> {
	using L = typename SplitImpl<pos, EmptyArray<T>, Array<T, values...>>::newL;
	using R = typename SplitImpl<pos, EmptyArray<T>, Array<T, values...>>::newR;
};

// merge:合并两个 Array
template <typename L, typename R>
struct Merge;

template <typename T, T... L, T... R>
struct Merge<Array<T, L...>, Array<T, R...>> {
	using type = Array<T, L..., R...>;
};

// get:读取某位置的元素
template <size_t pos, typename T>
struct Get;

template <size_t pos, typename T, T... values>
struct Get<pos, Array<T, values...>> {
	static constexpr T value = Array<T, values...>::data[pos];
};

// 其它同链表

int main() {
	using A1 = Array<int, 1, 2, 3, 4>;
	using A1l = Split<2, A1>::L;
	using A2 = Array<int, 3, 4, 5>;
	using A1l2 = Merge<A1l, A2>::type;

	[](...) {} (
		EmptyArray<int>::size,
		A1::size,

		Get<0, A1>::value,
		Get<3, A1>::value
		// Get<4, L1>::value // 可以在编译期检查越界(因为没有该模板的定义)
	);
}

归并排序

#include <iostream>
#include <type_traits>

template <int... values>
struct List;

template <>
struct List<> {
	static constexpr size_t size = 0;
};
using EmptyList = List<>;

template <int head, int... values>
struct List<head, values...> {
	static constexpr int front = head;
	static constexpr size_t size = 1 + sizeof...(values);
	using PopFrontT = std::conditional_t<size == 1, EmptyList, List<values...>>;
};

// --- insert
template <typename T, int value>
struct PushFront;

template <int... values, int x>
struct PushFront<List<values...>, x> {
	using type = List<x, values...>;
};

// --- split:将 List 从指定位置拆分成两个
template <size_t pos, typename L, typename R>
struct SplitImpl;

template <size_t now, int... L, int... R>
struct SplitImpl<now, List<L...>, List<R...>> { // 每次取出 R 中的一个放入 L
	using next = SplitImpl<now - 1, List<L..., List<R...>::front>, typename List<R...>::PopFrontT>;
	using newL = typename next::newL;
	using newR = typename next::newR;
};

template <int... L, int... R>
struct SplitImpl<0, List<L...>, List<R...>> {
	using newL = List<L...>;
	using newR = List<R...>;
};

template <size_t pos, typename T>
struct Split;

template <size_t pos, int... values>
struct Split<pos, List<values...>> {
	using L = typename SplitImpl<pos, EmptyList, List<values...>>::newL;
	using R = typename SplitImpl<pos, EmptyList, List<values...>>::newR;
};

// --- merge:合并两个 List
// template <typename L, typename R>
// struct Merge;

// template <int... L, int... R>
// struct Merge<List<L...>, List<R...>> {
// 	using type = List<L..., R...>;
// };

// --- merge:合并两个有序链表
template <typename L, typename R>
struct Merge;

template <int... L, int... R>
struct Merge<List<L...>, List<R...>> {
	using l = List<L...>;
	using r = List<R...>;
	static constexpr int min = l::front < r::front ? l::front : r::front;
	using temp = std::conditional_t<
		l::front < r::front,
		typename Merge<typename l::PopFrontT, r>::type,
		typename Merge<l, typename r::PopFrontT>::type
	>;
	using type = typename PushFront<temp, min>::type; // 每次取出较小值,然后递归处理后面的序列
};

// 递归边界
template <int... R>
struct Merge<EmptyList, List<R...>> {
	using type = List<R...>;
};

template <int... L>
struct Merge<List<L...>, EmptyList> {
	using type = List<L...>;
};

// --- mergeSort:归并排序:每次将链表拆分,递归排序,然后合并
template <typename L>
struct MergeSort;

template <int... values>
struct MergeSort<List<values...>> {
	using list = List<values...>;
	using l = Split<list::size / 2, list>::L;
	using r = Split<list::size / 2, list>::R;
	using sl = MergeSort<l>::type;
	using sr = MergeSort<r>::type;
	using type = Merge<sl, sr>::type;
};

// 模板递归需要定义边界!否则 MergeSort<List<values...>> 定义完之前无法递归使用 MergeSort<List<>> 和 MergeSort<List<v>>
template <int v>
struct MergeSort<List<v>> {
	using type = List<v>;
};

template <>
struct MergeSort<List<>> {
	using type = EmptyList;
};

// ---

int main() {
	using L1 = List<1, 4, 2, 3>;
	using L1l = Split<2, L1>::L;
	using L2 = List<2, 3, 4, 5>;
	using L1l2 = Merge<L1l, L2>::type;
	using L2pf = PushFront<L2, 2>::type;

	using S1 = Split<0, EmptyList>::L;
	using S2 = Split<0, EmptyList>::R;

	using R1 = MergeSort<EmptyList>::type;
	using R2 = MergeSort<List<3>>::type;

	using L3 = List<5, 2, 1, 9, 4, 2, 3, 0, 6>;
	using L3r = MergeSort<L3>::type;

	[](...) {} (
		EmptyList::size,
		L1::size,
		L3::size,
		L3r::size
	);
}

std::variant

#include <vector>
#include <cstring>
#include <cassert>
#include <variant>
#include <iostream>
#include <type_traits>

using std::cout;

/*
[variant](https://zh.cppreference.com/w/cpp/utility/variant)
- 切换类型时析构旧对象、创建新对象。
- 接口:get、emplace、swap。错误时抛出异常。
- 辅助类/函数:get、get_if、holds_alternative、variant_alternative、visit。
- 同一类型可以出现多次,但此时只能用下标访问。

基本实现就是利用 char 数组作为存储,其大小为各类型大小的最大值。在每次切换类型时析构并重新创建对象。
需要维护当前的类型 type,来验证读取的有效性(不能读取非上次写入的类型)。因为不能将类型作为变量,所以 type 是 int 下标。
析构时,需要根据 type 确定当前类型 T,以便将 data 转为 T* 然后调用 ~T()。可以用将每种类型的 Destroy 函数保存在一个函数指针数组里,用下标调用。
注意,下标到类型的转换、类型到下标的转换,都是只能在编译期进行的。type 是运行期变量,所以无法用于这些转换,必须手动指定或根据参数值推导出 T 或下标。

注意:
- data 要对齐。
- reinterpret_cast 本身不会隐式创建对象。切换时需要使用 placement new 构造。
- 由于指针可互转换的要求,即使 data 位置有新的对象,直接 reinterpret_cast 转换 data 访问也是 UB?需要 launder 或使用 placement new 返回的指针。
- 使用 T 初始化时应用 decay(T) 匹配。否则 "abc" *只会*直接匹配 const char&[4],然后才尝试隐式转换到 string 与 const char*(且按顺序选择),无法匹配 const char[4]。但是不需要支持保存数组,只存指针即可。
- 构造时应使用 T(...) 而非 T{...},对于有初始化列表构造函数的类(如 string、vector)会导致不同的结果。

未完善:
- Variant 在多种异常情况下会变得无值,通过 valueless_by_exception 检测。会影响多种函数的执行。
- Variant<float, long, double> z = 0; 应匹配 long。但我不知道怎么实现哪个更匹配,所以目前隐式转换会匹配第一个合适的类型,即使有多个或更合适的。
*/

// --- 获取类型最大大小与对齐
template <typename T, typename... Ts>
struct MaxSize {
	static constexpr size_t value = sizeof(T) >= MaxSize<Ts...>::value ? sizeof(T) : MaxSize<Ts...>::value;
};

template <typename T>
struct MaxSize<T> {
	static constexpr size_t value = sizeof(T);
};

// 其实不需要,alignas(T...) 也可展开。对象会取最大的对齐值
template <typename T, typename... Ts>
struct MaxAlign {
	static constexpr size_t value = alignof(T) >= MaxAlign<Ts...>::value ? alignof(T) : MaxAlign<Ts...>::value;
};

template <typename T>
struct MaxAlign<T> {
	static constexpr size_t value = alignof(T);
};

// --- 下标到类型的转换
template <size_t pos, typename T, typename... Ts>
struct IdToType {
	static_assert(pos < 1 + sizeof...(Ts));
	using type = typename IdToType<pos - 1, Ts...>::type;
};

template <typename T, typename... Ts>
struct IdToType<0, T, Ts...> {
	using type = T;
};

// --- 类型到下标的转换
template <size_t pos, typename X, typename T, typename... Ts>
struct TypeToIdImpl {
	static constexpr size_t value = std::is_same_v<X, T> ? pos : TypeToIdImpl<pos + 1, X, Ts...>::value;
};

template <size_t pos, typename X, typename T>
struct TypeToIdImpl<pos, X, T> {
	static constexpr size_t value = std::is_same_v<X, T> ? pos : (size_t)-1;
};

template <typename X, typename... Ts>
struct TypeToId {
	static constexpr size_t value = TypeToIdImpl<0, X, Ts...>::value;
};

// --- 类型到下标的转换,但允许隐式转换,类型不必完全相同
template <size_t pos, typename X, typename T, typename... Ts>
struct ConvertTypeToIdImpl {
	static constexpr size_t value = std::is_convertible_v<X, T> ? pos : ConvertTypeToIdImpl<pos + 1, X, Ts...>::value;
};

template <size_t pos, typename X, typename T>
struct ConvertTypeToIdImpl<pos, X, T> {
	static constexpr size_t value = std::is_convertible_v<X, T> ? pos : (size_t)-1;
};

template <typename X, typename... Ts>
struct ConvertTypeToId {
	static constexpr size_t value = ConvertTypeToIdImpl<0, X, Ts...>::value;
};

// --- utility
// 计算类型出现数量
template <typename X, typename T, typename... Ts>
struct CountType {
	static constexpr size_t value = (std::is_same_v<X, T> ? 1 : 0) + CountType<X, Ts...>::value;
};

template <typename X, typename T>
struct CountType<X, T> {
	static constexpr size_t value = (std::is_same_v<X, T> ? 1 : 0);
};

template <typename T, typename... Ts>
struct FirstType {
	using type = T;
};

// 判断 V 是否是模板 T 的实例化
template <template<typename...> class T, typename V> // T 拥有模板参数 typename...
struct T_is_instantiation_of: std::false_type {};

template <template<typename...> class T, typename... Ts>
struct T_is_instantiation_of<T, T<Ts...>>: std::true_type {};

template <template<size_t...> class T, typename V> // T 拥有模板参数 size_t...
struct V_is_instantiation_of: std::false_type {};

template <template<size_t...> class T, size_t... Ts>
struct V_is_instantiation_of<T, T<Ts...>>: std::true_type {};

// --- [消歧义标签](https://zh.cppreference.com/w/cpp/utility/in_place)
// 构造 Variant 时,需传递 std::in_place_type<T> 和 T 的构造参数,指明要使用的类型是 T(也可指明下标)
template <class T>
struct in_place_type_t {
    explicit in_place_type_t() = default;
};
template <class T>
inline constexpr in_place_type_t<T> in_place_type{};

template <std::size_t I>
struct in_place_index_t {
    explicit in_place_index_t() = default;
};
template <std::size_t I>
inline constexpr in_place_index_t<I> in_place_index{};

// --- 其它
template <typename... Ts>
struct Variant;

template <class T>
void DestroyImpl(unsigned char* data) {
	if constexpr (!std::is_trivially_destructible_v<T>) {
		std::launder(reinterpret_cast<T*>(data))->~T();
	}
}

// --- variant_alternative:将下标转为类型(获取当前选项)。如果 variant 有 const 限定则传给类型。
template <size_t I, class T>
struct variant_alternative;

template <std::size_t I, class... Ts>
struct variant_alternative<I, Variant<Ts...>> {
	static_assert(I < sizeof...(Ts));
	using type = IdToType<I, Ts...>::type;
};

template <std::size_t I, class... Ts>
class variant_alternative<I, const Variant<Ts...>> {
	static_assert(I < sizeof...(Ts));
	using type = std::add_const_t<typename IdToType<I, Ts...>::type>;
};

template <size_t I, class T>
using variant_alternative_t = variant_alternative<I, T>::type;

template <class T, class... Ts>
constexpr bool holds_alternative(const Variant<Ts...>& v) noexcept {
	try {
		v.template get<T>();
	} catch (const std::bad_variant_access&) {
		return false;
	}
	return true;
}

// --- variant
static constexpr size_t variant_npos = -1;

template <typename... Ts>
struct Variant {
	static_assert(sizeof...(Ts) > 0,
		"variant must have at least one alternative");
	static_assert(!(std::is_reference_v<Ts> || ...),
		"variant must have no reference alternative");
	static_assert(!(std::is_void_v<Ts> || ...),
		"variant must have no void alternative");

	using T0 = FirstType<Ts...>::type;

	constexpr Variant()
		noexcept(std::is_nothrow_default_constructible_v<T0>)
		requires std::is_default_constructible_v<T0>
	{
		type = 0;
		new (data) T0{};
	}
	/*
		没有办法在运行时得知当前 Variant 保存的类型,所以无法实现这两个构造函数。
		只有像下面的函数一样,将参数写为模板参数(编译期常量)才可以。
		将 Ts... 和当前的 type_info::name 作为 const char* 保存,可以实时判断当前的 typeid,但是没法把它转换回类型。
	*/
	Variant(const Variant& other) = delete;
	Variant(Variant&& other) = delete;
	// constexpr Variant(const Variant& other)
	// 	requires (std::is_copy_constructible_v<Ts> && ...)
	// {
	// 	type = other.type;
	// 	using T = IdToType<type, Ts...>::type; // error:type 不是编译时常量,不能用于编译期的类型获取
	// 	new (data) T(other.get<type>());
	// }
	// constexpr Variant(Variant&& other)
	//	requires (std::is_move_constructible_v<Ts> && ...)
	// {
	// 	type = other.type;
	// 	using T = IdToType<type, Ts...>::type;
	// 	new (data) T(std::move(other.get<type>()));
	// }

	template <class T>
	constexpr Variant(T&& t)
		requires (
			!std::is_same_v<std::decay_t<T>, Variant> &&
			!T_is_instantiation_of<in_place_type_t, T>::value &&
			!V_is_instantiation_of<in_place_index_t, T>::value &&
			(TypeToId<std::decay_t<T>, Ts...>::value != variant_npos || ConvertTypeToId<std::decay_t<T>, Ts...>::value != variant_npos)
		) // 可以再限制一下类型 T 在 Ts 的出现次数
	{
		using DT = std::decay_t<T>;
		constexpr size_t id = TypeToId<DT, Ts...>::value != variant_npos ? TypeToId<DT, Ts...>::value : ConvertTypeToId<DT, Ts...>::value;
		using RT = IdToType<id, Ts...>::type;
		static_assert(std::is_constructible_v<RT, T>);

		type = id;
		new (data) RT(std::forward<T>(t));
	}

	template <class T>
	Variant& operator =(T&& t)
		requires (
			!std::is_same_v<std::decay_t<T>, Variant> &&
			(TypeToId<std::decay_t<T>, Ts...>::value != variant_npos || ConvertTypeToId<std::decay_t<T>, Ts...>::value != variant_npos)
		)
	{
		using DT = std::decay_t<T>;
		constexpr size_t id = TypeToId<DT, Ts...>::value != variant_npos ? TypeToId<DT, Ts...>::value : ConvertTypeToId<DT, Ts...>::value;
		using RT = IdToType<id, Ts...>::type;
		static_assert(std::is_assignable_v<RT&, T>);

		Destroy();
		type = id;
		new (data) RT(std::forward<T>(t));
		return *this;
	}

	template <class T, class... Args>
	constexpr explicit Variant(in_place_type_t<T>, Args&&... args)
		requires (
			std::is_constructible_v<T, Args...> &&
			TypeToId<T, Ts...>::value != variant_npos &&
			CountType<T, Ts...>::value == 1
		)
	{
		type = TypeToId<T, Ts...>::value;
		new (data) T(std::forward<Args>(args)...);
	}

	template <size_t I, class... Args>
	constexpr explicit Variant(in_place_index_t<I>, Args&&... args)
		requires (I < sizeof...(Ts)) && std::is_constructible_v<typename IdToType<I, Ts...>::type, Args...>
	{
		type = I;
		using T = IdToType<I, Ts...>::type;
		new (data) T(std::forward<Args>(args)...);
	}

	// emplace
	template <class T, class... Args>
	T& emplace(Args&&... args)
		requires (
			std::is_constructible_v<T, Args...> &&
			CountType<T, Ts...>::value == 1
		)
	{
		Destroy();
		type = TypeToId<T, Ts...>::value;
		return *(new (data) T(std::forward<Args>(args)...));
	}

	template <std::size_t I, class... Args>
	variant_alternative_t<I, Variant>& emplace(Args&&... args)
		requires (I < sizeof...(Ts)) && std::is_constructible_v<typename IdToType<I, Ts...>::type, Args...>
	{
		Destroy();
		type = I;
		using T = IdToType<I, Ts...>::type;
		return *(new (data) T(std::forward<Args>(args)...));
	}

	void Destroy() {
		if (type != variant_npos) {
			destroy_funcs[type](data);
			type = variant_npos;
		}
	}

	// get
	template <typename T>
	T& get() {
		static_assert(CountType<T, Ts...>::value == 1);
		constexpr size_t index = TypeToId<T, Ts...>::value;
		return get<index>();
	}

	template <typename T>
	const T& get() const {
		static_assert(CountType<T, Ts...>::value == 1);
		constexpr size_t index = TypeToId<T, Ts...>::value;
		return get<index>();
	}

	template <size_t index>
	typename IdToType<index, Ts...>::type& get() {
		if (index != type) {
			throw std::bad_variant_access();
		}
		return *std::launder(reinterpret_cast<typename IdToType<index, Ts...>::type*>(data));
	}

	template <size_t index>
	const typename IdToType<index, Ts...>::type& get() const {
		if (index != type) {
			throw std::bad_variant_access();
		}
		return *std::launder(reinterpret_cast<typename IdToType<index, Ts...>::type*>(
			const_cast<unsigned char*>(data) // const this 只能获取到 const uchar*
		));
	}

	constexpr std::size_t index() const noexcept {
		return type;
	}

private:
	size_t type;
	// alignas(MaxAlign<Ts...>::value)
	alignas(Ts...) unsigned char data[MaxSize<Ts...>::value]; // alignas(T...) 也可展开。对象会取最大的对齐值

	using destroy_func_t = void (*)(unsigned char*);
	static constexpr destroy_func_t destroy_funcs[] = { DestroyImpl<Ts>... };
	// 注意不要与类内的 Destroy 定义重名,会优先选择后者
};

// template <typename... Ts>
// const typename Variant<Ts...>::destroy_func_t Variant<Ts...>::destroy_funcs[] = { DestroyImpl<Ts>... };

// --- 非成员函数
// --- get:通过下标/类型访问 variant 的当前值。
template <size_t I, class... Ts>
variant_alternative_t<I, Variant<Ts...>>& get(Variant<Ts...>& v) {
	return v.template get<I>();
}

template <size_t I, class... Ts>
const variant_alternative_t<I, Variant<Ts...>>& get(const Variant<Ts...>& v) {
	return v.template get<I>();
}

template <class T, class... Ts>
T& get(Variant<Ts...>& v) {
	return v.template get<T>();
}

template <class T, class... Ts>
const T& get(const Variant<Ts...>& v) {
	return v.template get<T>();
}

// --- get_if:返回 variant 当前值的指针。若下标/类型与当前值不符,或 pv 是空指针,则返回 nullptr 不抛出异常。
template <size_t I, class... Ts>
constexpr std::add_pointer_t<variant_alternative_t<I, Variant<Ts...>>>
get_if(Variant<Ts...>* pv) noexcept {
	if (I != pv->index()) {
		return nullptr;
	}
	return std::addressof(pv->template get<I>());
}

template <size_t I, class... Ts>
constexpr std::add_pointer_t<const variant_alternative_t<I, Variant<Ts...>>>
get_if(const Variant<Ts...>* pv) noexcept {
	if (I != pv->index()) {
		return nullptr;
	}
	return std::addressof(pv->template get<I>());
}

template <typename T, class... Ts>
constexpr T* get_if(Variant<Ts...>* pv) noexcept {
	constexpr size_t index = TypeToId<T, Ts...>::value;
	if (index != pv->index()) {
		return nullptr;
	}
	return std::addressof(pv->template get<T>());
}

template <typename T, class... Ts>
constexpr const T* get_if(const Variant<Ts...>* pv) noexcept {
	constexpr size_t index = TypeToId<T, Ts...>::value;
	if (index != pv->index()) {
		return nullptr;
	}
	return std::addressof(pv->template get<T>());
}

// ---
struct A {
	double a, b;
	A(): a(0), b(0) {}
	A(int i): a(i), b(i) {}
	bool operator ==(const A& x) const {
		return a == x.a && b == x.b;
	}
};
struct B {
	char c;
	B() {c=0;}
	B(char c): c(c) {}
	~B() {}
	B(const B& b) {c=b.c;}
	B(B&& b) {c=b.c; b.c=0;}
};

int add(int a, int b) {
	return a + b;
}
double minus(double a) {
	return -a;
}

int main() {
	using std::vector;
	using std::string;

	using std::get;
	using std::get_if;
	using std::holds_alternative;

#if false
	#define Variant std::variant
	#define in_place_type std::in_place_type
	#define in_place_index std::in_place_index
#endif

	A a{};
	B b{'0'};
	{
		Variant<A, char> v;
		assert((size_t)std::addressof(get<0>(v)) % 8 == 0);
		assert(alignof(get<0>(v)) == 8 && alignof(v) == 8);

		using V = Variant<A, int, B, string>;
		V v1;
		assert(holds_alternative<A>(v1) && v1.index() == 0 && get<A>(v1) == A{});
		assert(!holds_alternative<int>(v1));

		V v2{b};
		assert(v2.index() == 2 && get<2>(v2).c == '0' && b.c == '0');

		V v3{std::move(b)};
		assert(v3.index() == 2 && get<2>(v3).c == '0' && b.c == 0);

		V v4{"abc"};
		assert(v4.index() == 3 && get<3>(v4) == "abc");

		using V2 = Variant<A, vector<int>, string, char>;
		V2 a {in_place_type<vector<int>>, 3, (int)'a'};
		assert(a.index() == 1 && get<1>(a).size() == 3 && get<1>(a)[0] == 'a');

		V2 b {in_place_type<string>, 3, 'a'};
		assert(b.index() == 2 && get<2>(b) == "aaa");

		V2 c {in_place_index<1>, 3, 'a'};
		assert(c.index() == 1 && get<1>(c).size() == 3 && get<1>(c)[0] == 'a' && holds_alternative<vector<int>>(c));

		V2 d {in_place_index<2>, "ABCDE", 4};
		assert(d.index() == 2 && get<2>(d) == "ABCD" && holds_alternative<string>(d));
	}
	{
		Variant<int(*)(int, int), int, double(*)(double)> x = add;
		assert(get<0>(x)(1, 2) == 3);
		x.emplace<2>(minus);
		assert(get<2>(x)(3) == -3);
		x = add;
		assert(get<0>(x)(2, 3) == 5);

		Variant<string, bool, const char*> a = "abc";
		assert(a.index() == 2);

		// 不存放 const char[4]。"abc" 实际是 const char&[4],也需要 remove_ref
		Variant<string, const char*, const char[4]> b = "abc";
		assert(b.index() == 1);

		// Variant<A, in_place_index_t<1>> e;
		// e = in_place_index_t<1>{}; // error
	}
	// get
	{
		Variant<int, float> v;
		int& i = get<int>(v);
		assert(i == 0);
		i = 1;
		int j = get<0>(v);
		assert(j == 1);

		// get<3>(v); // 越界会有编译期模板错误
		// get_if<double>(&v); // 使用不存在的类型会有编译期模板错误
		try { // 抛异常
			get<float>(v);
			get<1>(v);
		}
		catch (const std::bad_variant_access&) {
			puts("catch");
		}

		assert(*get_if<0>(&v) == 1);
		assert(*get_if<int>(&v) == 1);
		assert(get_if<1>(&v) == nullptr);
		assert(get_if<float>(&v) == nullptr);
	}
	// operator =
	{
		Variant<string, string> v1;
		v1 = "abc";
		assert(v1.index() == 0 && get<0>(v1) == "abc");
		v1.emplace<1>("def");
		assert(v1.index() == 1 && get<1>(v1) == "def");

		using V = Variant<A, int, vector<int>, string>;
		V v2 {vector<int>{1, 2, 3}};
		assert(v2.index() == 2 && !holds_alternative<string>(v2));
		v2 = "abc";
		assert(v2.index() == 3 && get<string>(v2) == "abc");
		v2 = 3;
		assert(v2.index() == 1 && get<int>(v2) == 3);

		V v3 {1};
		assert(v3.index() == 1);
		v3 = vector<int>(2); // resize(2)
		get<2>(v3).push_back(1);
		get<2>(v3).push_back(2);
		for (const auto& v : get<2>(v3)) {
			cout << v << ' ';
		} cout << '\n';
	}
	// emplace
	{
		Variant<string, string> v1;
		v1.emplace<0>("abc");
		assert(v1.index() == 0 && get<0>(v1) == "abc");
		v1.emplace<1>("def");
		assert(v1.index() == 1 && get<1>(v1) == "def");

		using V = Variant<A, int, vector<int>, string>;
		V v2 {vector<int>{1, 2, 3}};
		assert(v2.index() == 2 && !holds_alternative<string>(v2));
		v2.emplace<string>("abc");
		assert(v2.index() == 3 && get<string>(v2) == "abc");
		v2.emplace<0>(3);
		assert(v2.index() == 0 && get<A>(v2) == A{3});

		V v3 {1};
		assert(v3.index() == 1);
		v3.emplace<2>(2); // resize(2)
		get<2>(v3).push_back(1);
		get<2>(v3).push_back(2);
		auto& vec = get<2>(v3);
		assert(vec[0] == 0 && vec[2] == 1 && vec[3] == 2);
	}
	// TODO
	{
		std::variant<float, long, double> b = 0;
		assert(b.index() == 1); // 目前实现的结果将是 0
	}

	// type check
	using i2t1 = IdToType<0, double, int, float, char[3]>::type;
	using i2t2 = IdToType<2, double, int, float, char[3]>::type;
	using i2t3 = IdToType<3, double, int, float, char[3]>::type;
	using f = FirstType<int, double, A[2]>::type;

	[](...) {}(
		MaxSize<int, char, double, char[3], A[2]>::value,
		MaxAlign<int, char, A, char[3], A[2]>::value,

		TypeToId<int, int, char[3], double, A>::value,
		TypeToId<char[3], int, char[3], double, A>::value,
		TypeToId<A[2], int, char[3], double, A[2]>::value,
		TypeToId<A[2], int, char[3], double, A>::value,

		TypeToId<const char*, std::string>::value,
		ConvertTypeToId<const char*, int, std::string>::value,
		ConvertTypeToId<const char*, std::string, std::string>::value,

		// std::is_same_v<const char*, const char[4]>, // false
		TypeToId<const char[4], std::string, const char*,  const char[4]>::value, // const char[4] 无意义,里面不需要放数组。此时直接匹配 const char*
		TypeToId<const char*, std::string, const char*>::value,
		ConvertTypeToId<const char[4], std::string, const char*>::value, // 实际应该是 1,判断时需用 decay(T)

		TypeToId<decltype(0), float, long, double>::value,
		ConvertTypeToId<decltype(0), float, long, double>::value, // 将匹配第一个 float,实际应该是 long

		T_is_instantiation_of<in_place_type_t, in_place_type_t<int>>::value,
		T_is_instantiation_of<in_place_type_t, in_place_index_t<1>>::value,
		V_is_instantiation_of<in_place_index_t, in_place_index_t<1>>::value

		// CheckAll<std::is_copy_constructible, A, int, B>::value
	);

}

std::any

#include <any>
#include <cstdio>
#include <vector>
#include <iostream>
#define pc putchar

using std::cout;
using std::string;
using std::vector;

template<typename T>
std::ostream& operator << (std::ostream& out, const vector<T>& v) {
	out << "[";
	for (auto it = v.begin(); it != v.end(); it++) {
		if (it != v.begin()) out << ", ";
		out << *it;
	}
	out << "]";
	return out;
}

class Any {
public:
	Any(): data(nullptr) {}
	Any(const Any& other) {
		if (other.data) {
			data = other.data->clone();
		}
	}
	Any(Any&& other): data{other.data} {
		other.data = nullptr;
	}
	Any& operator =(const Any& other) {
		if (this == &other) {
			return *this;
		}
		reset();
		if (other.data) {
			data = other.data->clone();
		}
		return *this;
	}
	Any& operator =(Any&& other) {
		reset();
		data = other.data;
		other.data = nullptr;
		return *this;
	}

	template <typename T,
			typename = std::enable_if_t<!std::is_same_v<Any, std::decay_t<T>>>>
	Any(T&& v): data(new Data<std::decay_t<T>>(std::forward<T>(v))) {}
	// 注意 Data 的模板上不能带引用,不然就不能用Data<T>准确获取了。但为了完美转发,构造函数上的T还是要带引用
	// 此外 Data 的成员 data 的类型也不能带引用,否则传左值时它就是 T&,会获取引用,而不是进行拷贝,可能导致悬垂引用!
	// 但与 remove_reference 相比,decay 更合适,见 function

	~Any() {
		reset();
	}

	template <typename T>
	T& any_cast() {
		auto p = data == nullptr ? nullptr : dynamic_cast<Data<T>*>(data);
		if (p == nullptr) {
			throw std::bad_any_cast();
		}
		return p->data;
		// return ((Data<T>*)data)->data;
	}

	void reset() noexcept {
		delete data;
	}

	void swap(Any& other) noexcept {
		std::swap(data, other.data);
	}

	const std::type_info& type() const noexcept {
		return data ? data->type() : typeid(nullptr);
	}

	friend std::ostream& operator << (std::ostream& out, const Any& any);

private:
	struct Base {
		virtual ~Base() {}
		virtual Base* clone() const = 0;
		virtual const std::type_info& type() const noexcept = 0;
		virtual std::ostream& print(std::ostream& out) = 0;
	};

	Base* data;

	template <typename T>
	struct Data: Base {
		template <typename UT>
		Data(UT&& v): data(std::forward<UT>(v)) {
			static_assert(std::is_same_v<T, std::decay_t<UT>>);
		}
		// 为了实现完美转发,构造函数中的模板必须带引用;但类本身的模板不能带引用,所以只能写两个模板参数

		Base* clone() const override {
			return new Data<T>(*this);
		}
		const std::type_info& type() const noexcept override {
			return typeid(T);
		}
		std::ostream& print(std::ostream& out) override { // 类型需要重载 operator <<
			out << data;
			return out;
		}

		T data;
	};
};

std::ostream& operator << (std::ostream& out, const Any& any) {
	if (any.data) {
		any.data->print(out);
	} else {
		out << "null";
	}
	return out;
}

struct Test {
	Test() { x = 0; debug && puts("Test()");}
	~Test() { debug && printf("~Test(%d)\n", x);}
	Test(const Test& o) { x = o.x; debug && puts("Test(const Test&)");}
	Test(Test&& o) { x = o.x; o.x = 0; debug && puts("Test(&&)");}

	int x;
	static constexpr bool debug = false;
};

int main() {
	if (true) {
		vector<Any> vec{1, 2.0, 3.f, "abc", vector<Any>{'a', "str"}};
		cout << vec << '\n';
		vec[2] = vector<int>{3, 3};
		cout << vec << '\n';
	}
	if (false) {
		Any a = Test();
		cout << a.any_cast<Test>().x << '\n'; // 0
	}
	if (false) {
		Test t;
		t.x = 1;
		Any b = t;
		cout << b.any_cast<Test>().x << '\n'; // 1
		t.x = 2;
		cout << b.any_cast<Test>().x << '\n'; // 1
		b.any_cast<Test>().x *= -1;
		Test t2 = b.any_cast<Test>();
		cout << t2.x << '\n'; // -1
		// copy
		Any c = b;
		Test& t3 = c.any_cast<Test>();
		cout << t3.x << '\n'; // -1
		t3.x --;
		cout << c.any_cast<Test>().x << '\n'; // -2
		Any d = std::move(c);
		try {
			cout << d.any_cast<Test>().x << '\n'; // -2
			cout << c.any_cast<Test>().x << '\n'; // error
		}
		catch(const std::exception& e) {
			std::cerr << e.what() << '\n';
		}
	}
	if (true) {
		Any a = 5;
		Any b = 1.f;
		Any c = std::vector<int>{1, 2};
		cout << a.type().name() << '\n';
		cout << b.type().name() << '\n';
		cout << c.type().name() << '\n';
	}

	cout << "end\n";

}

std::function

#include <cstdio>
#include <iostream>
#include <functional>
using std::cout;

// class bad_function_call: public std::exception {
// 	virtual const char* what() const noexcept {
// 		return "bad function call";
// 	}
// };

template <typename>
class Function;

template <typename R, typename... Args>
class Function<R(Args...)> {
public:
	Function(): callable(nullptr) {}

	Function(const Function& other) {
		if (other.callable) {
			callable = other.callable->clone();
		}
	}

	Function(Function&& other): callable(other.callable) { // 注意这里不要clone,直接获取值
		other.callable = nullptr;
	}

	template <typename F,
			typename = std::enable_if_t<!std::is_same_v<Function, std::decay_t<F>>>>
	Function(F&& f): callable(new NormalCallable<std::decay_t<F>>(std::forward<F>(f))) {}
	// 模板类型不能带引用,否则会产生悬垂引用,见 any
	// 但去除引用后,NormalCallable 的 F 会被推导为原类型,赋值函数时将是函数类型
	// 而数据成员的类型不能是函数类型。使用 decay 而非 remove_reference 刚好可做到这点(对于函数类型,会转为函数指针)
	// 但是 decay 后 Function g = f; 会匹配到这个模板构造函数,而非 Function(const Function&),除非加 enable_if 或 Function(Function&)

	template <typename C, typename Func>
	Function(Func C::* f): callable(new MemberFunctionPointer<C, Func>(std::forward<Func C::*>(f))) {}

	~Function() {
		delete callable;
	}

	operator bool() const noexcept {
		return this->callable != nullptr;
	}

	R operator()(Args... args) {
		if (static_cast<bool>(*this) == false) {
			throw std::bad_function_call();
		}
		return callable->invoke(std::forward<Args>(args)...);
	}

	void swap(Function &other) noexcept {
		std::swap(callable, other.callable);
	}

private:
	// 抽象基类,用于存储可调用对象的指针
	class BaseCallable {
	public:
		virtual R invoke(Args... args) = 0;
		virtual ~BaseCallable() {}
		virtual BaseCallable* clone() const = 0;
	};

	BaseCallable* callable;

	// 具体实现类,用于存储特定类型的可调用对象
	// #1 存储普通函数指针、仿函数、lambda、bind
	template <typename F>
	class NormalCallable : public BaseCallable {
	public:
		template <typename T>
		NormalCallable(T&& f) : func(std::forward<T>(f)) {
			// 对于仿函数,F为仿函数类型,T为 F&& 或 F&
			// 对于普通函数,F为函数指针,T为函数类型(可能带引用)
			static_assert(std::is_same_v<F, std::decay_t<T>>);
		}

		R invoke(Args... args) override {
			return func(std::forward<Args>(args)...);
		}

		BaseCallable* clone() const override {
			return new NormalCallable(*this);
		}

	private:
		F func;
	};

	// #2 存储函数成员指针
	template <typename C, typename F>
	class MemberFunctionPointer : public BaseCallable {
	public:
		MemberFunctionPointer(F C::*f) : func(f) {}

		R invoke(Args... args) override {
			return invokeImpl(args...);
		}
		template <typename... Args2>
		R invokeImpl(C& object, Args2... args) {
			return (object.*func)(std::forward<Args2>(args)...);
		}
		template <typename... Args2>
		R invokeImpl(const C& object, Args2... args) {
			return (object.*func)(std::forward<Args2>(args)...);
		}

		BaseCallable* clone() const override {
			return new MemberFunctionPointer(*this);
		}

	private:
		F C::*func;
	};
};

struct Node {
	Node(int x): x(x) {}
	int f(int v) {
		cout << "Node::f(" << v << ") x:" << x << '\n';
		return x;
	}
	int const_f(int v) const {
		cout << "Node::const_f(" << v << ") x:" << x << '\n';
		return x;
	}
	int x;
};
struct Func {
	int operator()(int x) {
		return x + 1;
	}
};

int add(int x) {
	return x + 1;
}
int add2(int x, int y) {
	return x + y;
}

int main() {
	// #define Function std::function
	// #1 存储普通函数指针
	Function<int (int)> f_add = add;
	cout << f_add(1) << '\n'; // 2
	Function<int (int)> f_add_c = f_add;
	cout << f_add_c(1) << '\n'; // 2

	// 通过 clone 创建新的 callable
	auto f_add2 = std::move(f_add);
	cout << f_add2(2) << '\n'; // 3
	// cout << f_add(2) << '\n'; // bad_function_call

	// #2 存储成员函数指针
	Node node{1};
	Function<int (Node&, int)> fp = &Node::f; // 通过Node&实例调用(也可以是const Node&)
	cout << fp(node, 2) << '\n'; // 1
	Function<int (const Node&, int)> fpc = &Node::const_f; // 通过const Node&实例调用
	cout << fpc(1, 2) << '\n'; // 1 隐式构造的右值可以绑定到const左值引用

	// 通过 clone 创建新的 callable
	auto fp2 = fp;
	cout << fp2(node, 3) << '\n'; // 1

	// #3 (不支持)存储数据成员指针
	// Function<int& (Node&)> fr = &Node::x; // 也可以是 int (const Node&)
	// cout << fr(node) << '\n'; // 1
	// fr(node) = 3;
	// cout << node.x << '\n'; // 3

	// #4 存储仿函数
	Function<int (int)> ff = Func();
	cout << ff(3) << '\n'; // 4

	// #5 存储lambda
	int tmp = 1;
	auto lam = [&tmp](int x) {
		tmp += x;
		return tmp;
	};
	Function<int (int)> f_lam = lam;
	cout << f_lam(2) << '\n'; // 3
	cout << tmp << '\n'; // 3

	// #6 存储bind表达式
	Function<int (int)> f_bind = std::bind(add2, 2, std::placeholders::_1);
	cout << f_bind(3) << '\n'; // 5
}

std::