-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmain.cpp
More file actions
108 lines (92 loc) · 2.42 KB
/
Copy pathmain.cpp
File metadata and controls
108 lines (92 loc) · 2.42 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
#include <any>
#include <print>
#include <functional>
#include <vector>
#include <numbers>
#include <meta>
template <class R, class T, class... Args>
constexpr R make_interface(Args&&... args)
{
R ret;
ret.value = T(std::forward<Args>(args)...);
constexpr auto ctx = std::meta::access_context::current();
// Iterate through all R's members
template for (constexpr auto ret_member : std::define_static_array(nonstatic_data_members_of(^^R, ctx)))
{
// Skips if its "value"
if constexpr (ret_member == ^^R::value)
{
continue;
}
// Iterate through all T's members
template for (constexpr auto t_member : std::define_static_array(members_of(^^T, ctx)))
{
// Skip if its not a function
if constexpr (!is_function(t_member))
{
continue;
}
// If the name matches, bind the functions together
if constexpr (has_identifier(ret_member) && has_identifier(t_member) && identifier_of(ret_member) == identifier_of(t_member))
{
ret.[:ret_member:] = std::bind(&[:t_member:], std::any_cast<T const&>(ret.value));
}
}
}
return ret;
}
class Circle
{
public:
explicit Circle(float radius) : _radius{radius}
{
}
float area() const
{
return std::numbers::pi_v<float> * _radius * _radius;
}
private:
float _radius = 0.0f;
};
class Rect
{
public:
explicit Rect(float length, float width) : _length{length}, _width{width}
{
}
float area() const
{
return _length * _width;
}
private:
float _length = 0.0f;
float _width = 0.0f;
};
struct Shape;
consteval
{
std::vector<std::meta::info> shape_members =
{
std::meta::data_member_spec(^^std::any, {.name = "value"}),
std::meta::data_member_spec(^^std::function<float()>, {.name = "area"}),
};
std::meta::define_aggregate(^^Shape, shape_members);
}
template <class T, class... Args>
constexpr auto make_shape(Args&&... args)
{
return make_interface<Shape, T>(std::forward<Args>(args)...);
}
int main()
{
std::vector<Shape> shapes;
shapes.push_back(make_shape<Circle>(1.0f));
shapes.push_back(make_shape<Rect>(1.0f, 2.0f));
for (auto const& shape : shapes)
{
std::println("{}", shape.area());
}
// Sample output:
// 3.1415927
// 2
}