Skip to content

Commit

Permalink
Merge pull request #225 from AzrBrk/main 修改第十题
Browse files Browse the repository at this point in the history
Update akchilov2.cpp
  • Loading branch information
Mq-b authored Jan 4, 2024
2 parents 55e1531 + f241344 commit 220d0dc
Showing 1 changed file with 160 additions and 172 deletions.
332 changes: 160 additions & 172 deletions src/群友提交/第10题/akchilov2.cpp
Original file line number Diff line number Diff line change
@@ -1,206 +1,194 @@
#include<type_traits>
#include<iostream>
#include<array>
#include<numeric>
#include<tuple>

//需要C++20以上
//这个程序的原理是用std::is_constructible猜测类的成员类型
//然后使用偏移量来访问类的数据成员
namespace my_utilities
#include<iostream>
namespace possibilities
{
struct inits
//需要C++20以上
//测试了MSVC latest, clang16, gcc13
//原理是用std::is_constructible猜测类的成员类型
//注意:需要给出类中可能出现的所有类型,但是不一定是精确的,可以多猜点,但是不能缺少,缺少会编译不过
namespace possibilities_utilities
{
template<class T> operator T();
};
struct inits
{
template<class T> operator T();
};
//这个类型用来试探某种类型是不是类的第N个成员类型
//由于std::is_constructible隐式转换也会true,所以这里禁止隐式转换以求结果精确
template<class T> struct convert_forbid
{
using type = T;
template<class U,class En = std::enable_if_t<std::is_same_v<T, U>>> operator U();
};
//计算成员数量,生成构造列表
template<bool, class T, class construct_list, std::size_t cnt> struct count_size{};
template<class T, template<class...> class construct_list, std::size_t cnt, class ...types>
struct count_size<true, T, construct_list<types...>, cnt>
{
static constexpr std::size_t value = cnt;
using CTL = construct_list<T, types...>;
};
template<class T, template<class ...> class construct_list, std::size_t cnt, class First, class ...rest>
struct count_size<false, T, construct_list<First, rest...>, cnt>
{
using next = count_size<std::is_constructible_v<T, First, rest...>,T, std::conditional_t<
std::is_constructible_v<T, First, rest...>, construct_list<First, rest...>, construct_list<rest...>>,
(std::is_constructible_v<T, First, rest...> ? cnt : cnt - 1)>;
static constexpr std::size_t value =next::value;
using CTL = typename next::CTL;
};
//工具类,用于替换构造列表中的元素
template<std::size_t N, class pre, class bck, class T> struct replace_at{};
template<std::size_t N, template<class...> class pre, template<class...> class bck, class RP, class bck_first, class ...preargs, class... bckargs>
struct replace_at<N, pre<preargs...>, bck<bck_first, bckargs...>, RP>
{
using type = typename replace_at<N - 1, pre<preargs..., bck_first>, bck<bckargs...>, RP>::type;
};

//这个类型用来试探某种类型是不是类的第N个成员类型
//由于std::is_constructible隐式转换也会true,所以这里禁止隐式转换
//以求结果精确
template<class T> struct convert_forbid
{
using type = T;
template<
class U,
class En = std::enable_if_t<std::is_same_v<T, U>>
> operator U();
};
//计算成员数量
template<bool, class T, class construct_list, size_t cnt> struct count_size
{
static constexpr size_t value = cnt;
};
template<class T, template<class ...> class construct_list, size_t cnt, class First, class ...rest>
struct count_size<false, T, construct_list<First, rest...>, cnt>
{
static constexpr size_t value =
count_size<
std::is_constructible_v<T, First, rest...>,
T,
construct_list<rest...>,
(std::is_constructible_v<T, First, rest...> ? cnt : cnt - 1)>
::value;
};
//工具类,选择类型分支
//本来我想用type_traits里面的,不熟悉就没用
template<bool cond, class A, class B> struct select_impl
{
using type = A;
};
template<template<class...> class pre, template<class...> class bck, class RP, class bck_first, class ...preargs, class... bckargs>
struct replace_at<0, pre<preargs...>, bck<bck_first, bckargs...>, RP>
{
using type = pre<preargs..., RP, bckargs...>;
};

template<class TL, template<class...> class Name> struct as_ {};
template<template<class...>class TL, template<class...>class Name, class ...Args> struct as_<TL<Args...>, Name>
{ using type = Name<Args...>; };
//在列表中选择元素
template<std::size_t N, class TL> struct select_element { using type = std::tuple_element_t<N, typename as_<TL, std::tuple>::type>; };
}
using namespace possibilities_utilities;

template<class ...> struct tl {};

template<class A, class B> struct select_impl<false, A, B>
template<class T> using count_size_type = count_size<false, std::decay_t<T>, tl<inits, inits, inits, inits, inits, inits, inits, inits, inits, inits>, 10>;
template<class T> constexpr std::size_t size() {
return count_size_type<T>::value;
}
//工具类,测试T的N个成员是否为Mem_type
template<std::size_t N, class T, class Mem_type> struct is_constructible_at
{
using type = B;
};
template<bool b, class A, class B> using select_branch = typename select_impl<b, A, B>::type;
using construct_list = typename count_size_type<T>::CTL;
using chk_constructible = typename replace_at<N + 1, tl<>, construct_list, convert_forbid<Mem_type>>::type;
using constructible_type = typename as_<chk_constructible, std::is_constructible>::type;
static constexpr bool value = constructible_type::value;

template<class T, class TL> struct add_front {};
template<class T, template<class...> class TL, class...Args> struct add_front<T, TL<Args...>>
};
//工具类,用一个列表mem_type_list逐个测试is_constructilbe_at,得到T的第N个成员的类型
template<bool constructible_, std::size_t N, class T, class mem_type_list> struct constructible_at_try {};
template<bool constructible_, std::size_t N, class T, template<class...> class mem_type_list, class first, class ...Args>
struct constructible_at_try<constructible_, N, T, mem_type_list<first, Args...>>
{
using type = TL<T, Args...>;
static constexpr bool cstible = is_constructible_at<N, T, first>::value;
using type = typename constructible_at_try<cstible, N, T,
std::conditional_t<cstible, mem_type_list<first, Args...>, mem_type_list<Args...>>>::type;
};

template<size_t N, class T, class TL> struct gen_list
{};

template<class T, template<class...> class TL, class ...Args> struct gen_list<0, T, TL<Args...>>
template<std::size_t N, class T, template<class...> class mem_type_list, class first, class ...Args>
struct constructible_at_try<true, N, T, mem_type_list<first, Args...>> {using type = first;};
//工具类,生成成员列表
template<std::size_t N, class T, class TL, class saved> struct make_construct_list {};
template<class T, template<class...> class TL, template<class...> class saved, class ...Args, class ...savedArgs>
struct make_construct_list<0, T, TL<Args...>, saved<savedArgs...>>
{
using type = TL<Args...>;
using current_type = typename constructible_at_try<false, 0, T, TL<Args...>>::type;
using type = saved<current_type, savedArgs...>;
};

template<size_t N, template<class...> class TL, class T, class ...Args> struct gen_list<N, T, TL<Args...>>
template<std::size_t N, class T, template<class...> class saved, class TL, class ...Args> struct make_construct_list<N, T, TL, saved<Args...>>
{
using type = typename gen_list<N - 1, T, TL<Args..., T>>::type;
using current_type = typename constructible_at_try<false, N, T, TL>::type;
using type = typename make_construct_list<N - 1, T, TL, saved<current_type, Args...>>::type;
};

template<class T, class Poss> using possibility = typename make_construct_list<possibilities::size<T>() - 1, T, Poss, tl<>>::type;
}


template<size_t N, class pre, class bck, class T> struct replace_at
namespace offset_pointer{
//offset_ptr模拟成员在结构体中的分布, advance:跨越一个指定的size的成员, forward_offset:寻找下一个成员的首地址
template<std::size_t pack_size, std::size_t layer_offset, std::size_t offset> struct offset_ptr
{
static_assert(pack_size <= 8, "An alignment size exceeds 8 is not tested!");
static constexpr std::size_t layer = layer_offset;//alignment layer as base
static constexpr std::size_t value = offset;//当前层偏移指针
static constexpr std::size_t half_pack = pack_size / 2;//层的半对齐
//工具:移动到下一内存对齐的层, 层偏移指针置零
template<std::size_t N> using advance_layer = offset_ptr<pack_size, layer + N, 0>;
//当forward offset + 当前层偏移超出或等于内存对齐的值
//假如forward offset+value==pack_size, 或则当前层偏移为0时,成员会存在当前层, 移动 size/pack_size + 1层,
//否则当size%pack_size == 0, size/pack_size + 2层,因为它会被放在下一层
//否则当size%pack_size != 0, size/pack_size + 3层(暂时没见过这种情况,数组可能会出现,但是这个类不让使用数组)
template<bool offset_overflow_pack, std::size_t forward_offset> struct advance_impl
{
static constexpr std::size_t forward_base = forward_offset / pack_size;
static constexpr bool has_rest = static_cast<bool>(forward_offset % pack_size);
static constexpr std::size_t forward_base_fixed = has_rest ? forward_base + 1 : forward_base;
using type = advance_layer<(((forward_offset + value) == 8) ? 0 : (value == 0 ? 0 : 1)) + forward_base_fixed>;
};
//当forward offset + 当前层偏移小于内存对齐的值,位移不超过当前层
//但是当forward offset超过半对齐,成员就会存储在后一半层, 否则直接移动forward offset
template<std::size_t forward_offset> struct advance_impl<false, forward_offset>
{
using type = offset_ptr<pack_size, layer, (value + forward_offset >= half_pack) ? pack_size : value + forward_offset>;
};
//工具:使指针越过一个成员的位置
template<std::size_t forward_offset> using advance = typename advance_impl<((value + forward_offset) >= pack_size), forward_offset>::type;
//探索指针,用于寻找下一个成员的首地址,只在get中使用
//枚举了给定的指针是否超过半对齐,内存对齐的情况
template<std::size_t forward_size> struct forward_impl
{
using type = std::conditional_t<(forward_size >= pack_size),
advance_layer<(value == 0)?0:1>, offset_ptr<pack_size, layer,
((forward_size >= half_pack) ? ((value == 0) ? 0 : half_pack) : 0) >>;
};
template<std::size_t forward_size> using forward_offset = typename forward_impl<forward_size>::type;
//基于当前的层偏移,使用探索指针寻找给定的类型的首地址
template<class T, class type> static type& get(T* ptr)
{
static_assert(!std::is_array_v<type>, "calculating size of an array is not tested!");
return *(reinterpret_cast<type*>(
reinterpret_cast<unsigned char*>(ptr) +
(
forward_offset<sizeof(type)>::layer * pack_size +
forward_offset<sizeof(type)>::value
)));
}
};

template<size_t N, template<class...> class pre, template<class...> class bck, class RP, class bck_first, class ...preargs, class... bckargs>
struct replace_at<N, pre<preargs...>, bck<bck_first, bckargs...>, RP>
//递归迭代,实现类似std::get的方法
template<std::size_t N, class offset_pointer, class TL> struct offset_iter {};
template<std::size_t N, class offset_pointer, template<class ...> class TL, class first, class ...rest>
struct offset_iter<N, offset_pointer, TL<first, rest...>>
{
using type = typename replace_at<N - 1, pre<preargs..., bck_first>, bck<bckargs...>, RP>::type;
};
using recurse_type = offset_iter<N - 1, typename offset_pointer::template advance<sizeof(first)>, TL<rest...>>;
using iter_type = typename recurse_type::iter_type;
using type = typename recurse_type::type;

template<template<class...> class pre, template<class...> class bck, class RP, class bck_first, class ...preargs, class... bckargs>
struct replace_at<0, pre<preargs...>, bck<bck_first, bckargs...>, RP>
{
using type = pre<preargs..., RP, bckargs...>;
};

template<class TL, template<class...> class Name> struct as_ {};
template<template<class...>class TL, template<class...>class Name, class ...Args> struct as_<TL<Args...>, Name>
template<class offset_pointer, template<class...> class TL, class first, class ...rest>
struct offset_iter<0, offset_pointer, TL<first, rest...>>
{
using type = Name<Args...>;
using type = first;
using iter_type = offset_pointer;
};
template<class ...> struct tl {};

//在列表种选择元素
//懒得写了,骗一下这个tuple_element_t
template<size_t N, class TL> struct select_element { using type = std::tuple_element_t<N, typename as_<TL, std::tuple>::type>; };

}
using namespace my_utilities;


template<class T> constexpr size_t size()
{
return count_size<false, std::decay_t<T>, tl<inits, inits, inits, inits, inits, inits, inits, inits, inits, inits>, 10>::value;
}


//工具类,测试T的N个成员是否为Mem_type
template<size_t N, class T, class Mem_type> struct is_constructible_at
{
using construct_list = typename gen_list<size<T>(), inits, tl<T>>::type;
using chk_constructible = typename replace_at<N + 1, tl<>, construct_list, convert_forbid<Mem_type>>::type;

using constructible_type = typename as_<chk_constructible, std::is_constructible>::type;
static constexpr bool value = constructible_type::value;

};
//工具类,用一个列表mem_type_list逐个测试is_constructilbe_at,得到T的第N个成员的类型
template<bool constructible_, size_t N, class T, class mem_type_list> struct constructible_at_try {};
template<bool constructible_, size_t N, class T, template<class...> class mem_type_list, class first, class ...Args>
struct constructible_at_try<constructible_, N, T, mem_type_list<first, Args...>>
{
static constexpr bool cstible = is_constructible_at<N, T, first>::value;
using type = typename constructible_at_try<cstible,
N,
T,
select_branch<cstible, mem_type_list<first, Args...>, mem_type_list<Args...>
>
>::type;
};

template<size_t N, class T, template<class...> class mem_type_list, class first, class ...Args> struct constructible_at_try<true, N, T, mem_type_list<first, Args...>>
{
using type = first;
};
//工具类,生成成员列表
template<size_t N, class T, class TL, class saved> struct make_construct_list
{};
template<class T, template<class...> class TL, template<class...> class saved, class ...Args, class ...savedArgs> struct make_construct_list<0, T, TL<Args...>, saved<savedArgs...>>
{
using current_type = typename constructible_at_try<false, 0, T, TL<Args...>>::type;
using type = typename add_front<current_type, saved<savedArgs...>>::type;
};
template<size_t N, class T, template<class...> class saved, class TL, class ...Args> struct make_construct_list<N, T, TL, saved<Args...>>
{
using current_type = typename constructible_at_try<false, N, T, TL>::type;
using type = typename make_construct_list<N - 1, T, TL, saved<current_type, Args...>>::type;
};


//计算偏移
template<size_t pack_size, template<class...> class TL, class ...Typs> constexpr auto make_offset_list(TL<Typs...>)
{
return std::array{ (sizeof(Typs) % pack_size ? sizeof(Typs) / pack_size * pack_size + pack_size : sizeof(Typs))... };
}


template<size_t pack_size, class T, class possibilities> class offset_pointer
{
using construct_list = typename make_construct_list<size<T>() - 1, T, possibilities, tl<>>::type;
public:
offset_pointer(T* a) noexcept : baseptr(reinterpret_cast<unsigned char*>(a)) {}
template<size_t I> typename select_element<I, construct_list>::type get() const
//封装成函数
template<std::size_t I, class CTL, class T> auto& get_member(T* x)
{
if constexpr (I == 0) {
return *(reinterpret_cast<std::add_pointer_t<typename select_element<0, construct_list>::type>>(baseptr));
}
else
{
return *(
reinterpret_cast<std::add_pointer_t<typename select_element<I, construct_list>::type>>(
baseptr + std::accumulate(member_offset.begin() + 1, member_offset.begin() + 1 + I, 0)
)
);
}
using types_iter = offset_iter<I, offset_ptr<alignof(T), 0, 0>, CTL>;
return types_iter::iter_type::template get<T, typename types_iter::type>(x);
}
private:
unsigned char* baseptr;
std::array<size_t, size<T>()>
member_offset{
make_offset_list<pack_size>(typename make_construct_list<size<T>() - 1, T, possibilities, tl<>>::type())
};
};
}

using namespace possibilities;
using namespace offset_pointer;
using possible = tl<int, std::string, double, char>;

//理论上可以算内存对齐,但是已经太长了,不想写那个了
template<class T, class F, size_t ...I> void for_each_member_impl(T&& t, F&& f, std::index_sequence<I...>)
template<class T, class F, size_t ...I> constexpr void for_each_member_impl(T&& x, F&& f, std::index_sequence<I...>)
{
//有点上帝视角了,因为已经看到了所有的数据类型
using possible_types = tl<int, std::string, double>;
offset_pointer<alignof(T), T, possible_types> op{ &t };
(f(op.template get<I>()), ...);
((f(get_member<I, possibility<T, possible>>(&x))), ...);
}

template<class T, class F> constexpr void for_each_member(T&& t, F&& f)
template<class T, class F> constexpr void for_each_member(T&& x, F&& f)
{
for_each_member_impl(std::move(t), std::move(f), std::make_index_sequence<size<T>()>{});
for_each_member_impl(std::move(x), std::move(f), std::make_index_sequence<size<T>()>{});
}

int main() {
Expand Down

0 comments on commit 220d0dc

Please sign in to comment.