Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update akchilov2.cpp #225

Merged
merged 3 commits into from
Jan 4, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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