Skip to content

Commit 2fba757

Browse files
authored
Merge pull request #225 from AzrBrk/main 修改第十题
Update akchilov2.cpp
2 parents 802adac + 7cc91ba commit 2fba757

File tree

1 file changed

+160
-172
lines changed

1 file changed

+160
-172
lines changed

src/群友提交/第10题/akchilov2.cpp

+160-172
Original file line numberDiff line numberDiff line change
@@ -1,206 +1,194 @@
11
#include<type_traits>
2-
#include<iostream>
3-
#include<array>
4-
#include<numeric>
52
#include<tuple>
6-
7-
//需要C++20以上
8-
//这个程序的原理是用std::is_constructible猜测类的成员类型
9-
//然后使用偏移量来访问类的数据成员
10-
namespace my_utilities
3+
#include<iostream>
4+
namespace possibilities
115
{
12-
struct inits
6+
//需要C++20以上
7+
//测试了MSVC latest, clang16, gcc13
8+
//原理是用std::is_constructible猜测类的成员类型
9+
//注意:需要给出类中可能出现的所有类型,但是不一定是精确的,可以多猜点,但是不能缺少,缺少会编译不过
10+
namespace possibilities_utilities
1311
{
14-
template<class T> operator T();
15-
};
12+
struct inits
13+
{
14+
template<class T> operator T();
15+
};
16+
//这个类型用来试探某种类型是不是类的第N个成员类型
17+
//由于std::is_constructible隐式转换也会true,所以这里禁止隐式转换以求结果精确
18+
template<class T> struct convert_forbid
19+
{
20+
using type = T;
21+
template<class U,class En = std::enable_if_t<std::is_same_v<T, U>>> operator U();
22+
};
23+
//计算成员数量,生成构造列表
24+
template<bool, class T, class construct_list, std::size_t cnt> struct count_size{};
25+
template<class T, template<class...> class construct_list, std::size_t cnt, class ...types>
26+
struct count_size<true, T, construct_list<types...>, cnt>
27+
{
28+
static constexpr std::size_t value = cnt;
29+
using CTL = construct_list<T, types...>;
30+
};
31+
template<class T, template<class ...> class construct_list, std::size_t cnt, class First, class ...rest>
32+
struct count_size<false, T, construct_list<First, rest...>, cnt>
33+
{
34+
using next = count_size<std::is_constructible_v<T, First, rest...>,T, std::conditional_t<
35+
std::is_constructible_v<T, First, rest...>, construct_list<First, rest...>, construct_list<rest...>>,
36+
(std::is_constructible_v<T, First, rest...> ? cnt : cnt - 1)>;
37+
static constexpr std::size_t value =next::value;
38+
using CTL = typename next::CTL;
39+
};
40+
//工具类,用于替换构造列表中的元素
41+
template<std::size_t N, class pre, class bck, class T> struct replace_at{};
42+
template<std::size_t N, template<class...> class pre, template<class...> class bck, class RP, class bck_first, class ...preargs, class... bckargs>
43+
struct replace_at<N, pre<preargs...>, bck<bck_first, bckargs...>, RP>
44+
{
45+
using type = typename replace_at<N - 1, pre<preargs..., bck_first>, bck<bckargs...>, RP>::type;
46+
};
1647

17-
//这个类型用来试探某种类型是不是类的第N个成员类型
18-
//由于std::is_constructible隐式转换也会true,所以这里禁止隐式转换
19-
//以求结果精确
20-
template<class T> struct convert_forbid
21-
{
22-
using type = T;
23-
template<
24-
class U,
25-
class En = std::enable_if_t<std::is_same_v<T, U>>
26-
> operator U();
27-
};
28-
//计算成员数量
29-
template<bool, class T, class construct_list, size_t cnt> struct count_size
30-
{
31-
static constexpr size_t value = cnt;
32-
};
33-
template<class T, template<class ...> class construct_list, size_t cnt, class First, class ...rest>
34-
struct count_size<false, T, construct_list<First, rest...>, cnt>
35-
{
36-
static constexpr size_t value =
37-
count_size<
38-
std::is_constructible_v<T, First, rest...>,
39-
T,
40-
construct_list<rest...>,
41-
(std::is_constructible_v<T, First, rest...> ? cnt : cnt - 1)>
42-
::value;
43-
};
44-
//工具类,选择类型分支
45-
//本来我想用type_traits里面的,不熟悉就没用
46-
template<bool cond, class A, class B> struct select_impl
47-
{
48-
using type = A;
49-
};
48+
template<template<class...> class pre, template<class...> class bck, class RP, class bck_first, class ...preargs, class... bckargs>
49+
struct replace_at<0, pre<preargs...>, bck<bck_first, bckargs...>, RP>
50+
{
51+
using type = pre<preargs..., RP, bckargs...>;
52+
};
53+
54+
template<class TL, template<class...> class Name> struct as_ {};
55+
template<template<class...>class TL, template<class...>class Name, class ...Args> struct as_<TL<Args...>, Name>
56+
{ using type = Name<Args...>; };
57+
//在列表中选择元素
58+
template<std::size_t N, class TL> struct select_element { using type = std::tuple_element_t<N, typename as_<TL, std::tuple>::type>; };
59+
}
60+
using namespace possibilities_utilities;
61+
62+
template<class ...> struct tl {};
5063

51-
template<class A, class B> struct select_impl<false, A, B>
64+
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>;
65+
template<class T> constexpr std::size_t size() {
66+
return count_size_type<T>::value;
67+
}
68+
//工具类,测试T的N个成员是否为Mem_type
69+
template<std::size_t N, class T, class Mem_type> struct is_constructible_at
5270
{
53-
using type = B;
54-
};
55-
template<bool b, class A, class B> using select_branch = typename select_impl<b, A, B>::type;
71+
using construct_list = typename count_size_type<T>::CTL;
72+
using chk_constructible = typename replace_at<N + 1, tl<>, construct_list, convert_forbid<Mem_type>>::type;
73+
using constructible_type = typename as_<chk_constructible, std::is_constructible>::type;
74+
static constexpr bool value = constructible_type::value;
5675

57-
template<class T, class TL> struct add_front {};
58-
template<class T, template<class...> class TL, class...Args> struct add_front<T, TL<Args...>>
76+
};
77+
//工具类,用一个列表mem_type_list逐个测试is_constructilbe_at,得到T的第N个成员的类型
78+
template<bool constructible_, std::size_t N, class T, class mem_type_list> struct constructible_at_try {};
79+
template<bool constructible_, std::size_t N, class T, template<class...> class mem_type_list, class first, class ...Args>
80+
struct constructible_at_try<constructible_, N, T, mem_type_list<first, Args...>>
5981
{
60-
using type = TL<T, Args...>;
82+
static constexpr bool cstible = is_constructible_at<N, T, first>::value;
83+
using type = typename constructible_at_try<cstible, N, T,
84+
std::conditional_t<cstible, mem_type_list<first, Args...>, mem_type_list<Args...>>>::type;
6185
};
6286

63-
template<size_t N, class T, class TL> struct gen_list
64-
{};
65-
66-
template<class T, template<class...> class TL, class ...Args> struct gen_list<0, T, TL<Args...>>
87+
template<std::size_t N, class T, template<class...> class mem_type_list, class first, class ...Args>
88+
struct constructible_at_try<true, N, T, mem_type_list<first, Args...>> {using type = first;};
89+
//工具类,生成成员列表
90+
template<std::size_t N, class T, class TL, class saved> struct make_construct_list {};
91+
template<class T, template<class...> class TL, template<class...> class saved, class ...Args, class ...savedArgs>
92+
struct make_construct_list<0, T, TL<Args...>, saved<savedArgs...>>
6793
{
68-
using type = TL<Args...>;
94+
using current_type = typename constructible_at_try<false, 0, T, TL<Args...>>::type;
95+
using type = saved<current_type, savedArgs...>;
6996
};
70-
71-
template<size_t N, template<class...> class TL, class T, class ...Args> struct gen_list<N, T, TL<Args...>>
97+
template<std::size_t N, class T, template<class...> class saved, class TL, class ...Args> struct make_construct_list<N, T, TL, saved<Args...>>
7298
{
73-
using type = typename gen_list<N - 1, T, TL<Args..., T>>::type;
99+
using current_type = typename constructible_at_try<false, N, T, TL>::type;
100+
using type = typename make_construct_list<N - 1, T, TL, saved<current_type, Args...>>::type;
74101
};
75102

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

77-
78-
template<size_t N, class pre, class bck, class T> struct replace_at
106+
namespace offset_pointer{
107+
//offset_ptr模拟成员在结构体中的分布, advance:跨越一个指定的size的成员, forward_offset:寻找下一个成员的首地址
108+
template<std::size_t pack_size, std::size_t layer_offset, std::size_t offset> struct offset_ptr
79109
{
110+
static_assert(pack_size <= 8, "An alignment size exceeds 8 is not tested!");
111+
static constexpr std::size_t layer = layer_offset;//alignment layer as base
112+
static constexpr std::size_t value = offset;//当前层偏移指针
113+
static constexpr std::size_t half_pack = pack_size / 2;//层的半对齐
114+
//工具:移动到下一内存对齐的层, 层偏移指针置零
115+
template<std::size_t N> using advance_layer = offset_ptr<pack_size, layer + N, 0>;
116+
//当forward offset + 当前层偏移超出或等于内存对齐的值
117+
//假如forward offset+value==pack_size, 或则当前层偏移为0时,成员会存在当前层, 移动 size/pack_size + 1层,
118+
//否则当size%pack_size == 0, size/pack_size + 2层,因为它会被放在下一层
119+
//否则当size%pack_size != 0, size/pack_size + 3层(暂时没见过这种情况,数组可能会出现,但是这个类不让使用数组)
120+
template<bool offset_overflow_pack, std::size_t forward_offset> struct advance_impl
121+
{
122+
static constexpr std::size_t forward_base = forward_offset / pack_size;
123+
static constexpr bool has_rest = static_cast<bool>(forward_offset % pack_size);
124+
static constexpr std::size_t forward_base_fixed = has_rest ? forward_base + 1 : forward_base;
125+
using type = advance_layer<(((forward_offset + value) == 8) ? 0 : (value == 0 ? 0 : 1)) + forward_base_fixed>;
126+
};
127+
//当forward offset + 当前层偏移小于内存对齐的值,位移不超过当前层
128+
//但是当forward offset超过半对齐,成员就会存储在后一半层, 否则直接移动forward offset
129+
template<std::size_t forward_offset> struct advance_impl<false, forward_offset>
130+
{
131+
using type = offset_ptr<pack_size, layer, (value + forward_offset >= half_pack) ? pack_size : value + forward_offset>;
132+
};
133+
//工具:使指针越过一个成员的位置
134+
template<std::size_t forward_offset> using advance = typename advance_impl<((value + forward_offset) >= pack_size), forward_offset>::type;
135+
//探索指针,用于寻找下一个成员的首地址,只在get中使用
136+
//枚举了给定的指针是否超过半对齐,内存对齐的情况
137+
template<std::size_t forward_size> struct forward_impl
138+
{
139+
using type = std::conditional_t<(forward_size >= pack_size),
140+
advance_layer<(value == 0)?0:1>, offset_ptr<pack_size, layer,
141+
((forward_size >= half_pack) ? ((value == 0) ? 0 : half_pack) : 0) >>;
142+
};
143+
template<std::size_t forward_size> using forward_offset = typename forward_impl<forward_size>::type;
144+
//基于当前的层偏移,使用探索指针寻找给定的类型的首地址
145+
template<class T, class type> static type& get(T* ptr)
146+
{
147+
static_assert(!std::is_array_v<type>, "calculating size of an array is not tested!");
148+
return *(reinterpret_cast<type*>(
149+
reinterpret_cast<unsigned char*>(ptr) +
150+
(
151+
forward_offset<sizeof(type)>::layer * pack_size +
152+
forward_offset<sizeof(type)>::value
153+
)));
154+
}
80155
};
81-
82-
template<size_t N, template<class...> class pre, template<class...> class bck, class RP, class bck_first, class ...preargs, class... bckargs>
83-
struct replace_at<N, pre<preargs...>, bck<bck_first, bckargs...>, RP>
156+
//递归迭代,实现类似std::get的方法
157+
template<std::size_t N, class offset_pointer, class TL> struct offset_iter {};
158+
template<std::size_t N, class offset_pointer, template<class ...> class TL, class first, class ...rest>
159+
struct offset_iter<N, offset_pointer, TL<first, rest...>>
84160
{
85-
using type = typename replace_at<N - 1, pre<preargs..., bck_first>, bck<bckargs...>, RP>::type;
86-
};
161+
using recurse_type = offset_iter<N - 1, typename offset_pointer::template advance<sizeof(first)>, TL<rest...>>;
162+
using iter_type = typename recurse_type::iter_type;
163+
using type = typename recurse_type::type;
87164

88-
template<template<class...> class pre, template<class...> class bck, class RP, class bck_first, class ...preargs, class... bckargs>
89-
struct replace_at<0, pre<preargs...>, bck<bck_first, bckargs...>, RP>
90-
{
91-
using type = pre<preargs..., RP, bckargs...>;
92165
};
93-
94-
template<class TL, template<class...> class Name> struct as_ {};
95-
template<template<class...>class TL, template<class...>class Name, class ...Args> struct as_<TL<Args...>, Name>
166+
template<class offset_pointer, template<class...> class TL, class first, class ...rest>
167+
struct offset_iter<0, offset_pointer, TL<first, rest...>>
96168
{
97-
using type = Name<Args...>;
169+
using type = first;
170+
using iter_type = offset_pointer;
98171
};
99-
template<class ...> struct tl {};
100-
101-
//在列表种选择元素
102-
//懒得写了,骗一下这个tuple_element_t
103-
template<size_t N, class TL> struct select_element { using type = std::tuple_element_t<N, typename as_<TL, std::tuple>::type>; };
104-
105-
}
106-
using namespace my_utilities;
107-
108-
109-
template<class T> constexpr size_t size()
110-
{
111-
return count_size<false, std::decay_t<T>, tl<inits, inits, inits, inits, inits, inits, inits, inits, inits, inits>, 10>::value;
112-
}
113-
114-
115-
//工具类,测试T的N个成员是否为Mem_type
116-
template<size_t N, class T, class Mem_type> struct is_constructible_at
117-
{
118-
using construct_list = typename gen_list<size<T>(), inits, tl<T>>::type;
119-
using chk_constructible = typename replace_at<N + 1, tl<>, construct_list, convert_forbid<Mem_type>>::type;
120-
121-
using constructible_type = typename as_<chk_constructible, std::is_constructible>::type;
122-
static constexpr bool value = constructible_type::value;
123-
124-
};
125-
//工具类,用一个列表mem_type_list逐个测试is_constructilbe_at,得到T的第N个成员的类型
126-
template<bool constructible_, size_t N, class T, class mem_type_list> struct constructible_at_try {};
127-
template<bool constructible_, size_t N, class T, template<class...> class mem_type_list, class first, class ...Args>
128-
struct constructible_at_try<constructible_, N, T, mem_type_list<first, Args...>>
129-
{
130-
static constexpr bool cstible = is_constructible_at<N, T, first>::value;
131-
using type = typename constructible_at_try<cstible,
132-
N,
133-
T,
134-
select_branch<cstible, mem_type_list<first, Args...>, mem_type_list<Args...>
135-
>
136-
>::type;
137-
};
138-
139-
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...>>
140-
{
141-
using type = first;
142-
};
143-
//工具类,生成成员列表
144-
template<size_t N, class T, class TL, class saved> struct make_construct_list
145-
{};
146-
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...>>
147-
{
148-
using current_type = typename constructible_at_try<false, 0, T, TL<Args...>>::type;
149-
using type = typename add_front<current_type, saved<savedArgs...>>::type;
150-
};
151-
template<size_t N, class T, template<class...> class saved, class TL, class ...Args> struct make_construct_list<N, T, TL, saved<Args...>>
152-
{
153-
using current_type = typename constructible_at_try<false, N, T, TL>::type;
154-
using type = typename make_construct_list<N - 1, T, TL, saved<current_type, Args...>>::type;
155-
};
156-
157-
158-
//计算偏移
159-
template<size_t pack_size, template<class...> class TL, class ...Typs> constexpr auto make_offset_list(TL<Typs...>)
160-
{
161-
return std::array{ (sizeof(Typs) % pack_size ? sizeof(Typs) / pack_size * pack_size + pack_size : sizeof(Typs))... };
162-
}
163-
164-
165-
template<size_t pack_size, class T, class possibilities> class offset_pointer
166-
{
167-
using construct_list = typename make_construct_list<size<T>() - 1, T, possibilities, tl<>>::type;
168-
public:
169-
offset_pointer(T* a) noexcept : baseptr(reinterpret_cast<unsigned char*>(a)) {}
170-
template<size_t I> typename select_element<I, construct_list>::type get() const
172+
//封装成函数
173+
template<std::size_t I, class CTL, class T> auto& get_member(T* x)
171174
{
172-
if constexpr (I == 0) {
173-
return *(reinterpret_cast<std::add_pointer_t<typename select_element<0, construct_list>::type>>(baseptr));
174-
}
175-
else
176-
{
177-
return *(
178-
reinterpret_cast<std::add_pointer_t<typename select_element<I, construct_list>::type>>(
179-
baseptr + std::accumulate(member_offset.begin() + 1, member_offset.begin() + 1 + I, 0)
180-
)
181-
);
182-
}
175+
using types_iter = offset_iter<I, offset_ptr<alignof(T), 0, 0>, CTL>;
176+
return types_iter::iter_type::template get<T, typename types_iter::type>(x);
183177
}
184-
private:
185-
unsigned char* baseptr;
186-
std::array<size_t, size<T>()>
187-
member_offset{
188-
make_offset_list<pack_size>(typename make_construct_list<size<T>() - 1, T, possibilities, tl<>>::type())
189-
};
190-
};
178+
}
179+
180+
using namespace possibilities;
181+
using namespace offset_pointer;
182+
using possible = tl<int, std::string, double, char>;
191183

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

201-
template<class T, class F> constexpr void for_each_member(T&& t, F&& f)
189+
template<class T, class F> constexpr void for_each_member(T&& x, F&& f)
202190
{
203-
for_each_member_impl(std::move(t), std::move(f), std::make_index_sequence<size<T>()>{});
191+
for_each_member_impl(std::move(x), std::move(f), std::make_index_sequence<size<T>()>{});
204192
}
205193

206194
int main() {

0 commit comments

Comments
 (0)