HikoGUI
A low latency retained GUI
Loading...
Searching...
No Matches
reflection.hpp
1// Copyright Take Vos 2022.
2// Distributed under the Boost Software License, Version 1.0.
3// (See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt)
4
5#pragma once
6
7#include "utility/module.hpp"
8#include <type_traits>
9#include <string>
10#include <string_view>
11
12namespace hi { inline namespace v1 {
13
17 template<typename T>
18 [[nodiscard]] constexpr operator T() const noexcept
19 {
20 return {};
21 }
22};
23
24namespace detail {
25
26template<typename T, typename... C>
27[[nodiscard]] constexpr size_t count_data_members() noexcept
28{
29 static_assert(std::is_trivially_constructible_v<T>);
30
31 // Try the largest possible number of data members first. i.e. depth-first recursive.
32 if constexpr (sizeof...(C) < sizeof(T)) {
33 if constexpr (constexpr auto next = count_data_members<T, C..., convertible_to_any>()) {
34 // We found the number of data members, larger than the current size.
35 return next;
36 }
37 }
38
39 // Check if this number of arguments to the constructor is valid .
40 if constexpr (requires { T{C{}...}; }) {
41 // Yes, return the number of arguments.
42 return sizeof...(C);
43 } else {
44 // Nope, return false.
45 return 0;
46 }
47}
48
49[[nodiscard]] constexpr std::string_view type_name_token(std::string_view str) noexcept
50{
51 for (auto i = 0_uz; i != str.size(); ++i) {
52 hilet c = str[i];
53
54 if (not((c >= 'a' and c <= 'z') or (c >= 'A' and c <= 'Z') or (c >= '0' and c <= '9') or c == '_')) {
55 // End of token.
56 return str.substr(0, i + 1);
57 }
58 }
59
60 return str;
61}
62
63[[nodiscard]] constexpr std::string type_name_short_hand(std::string_view type_name) noexcept
64{
65 if (type_name == "std::basic_string<char,std::char_traits<char>,std::allocator<char>>") {
66 return "std::string";
67 } else if (type_name == "std::basic_string<char,std::char_traits<char>,std::allocator<char>>&") {
68 return "std::string&";
69 } else if (type_name == "const std::basic_string<char,std::char_traits<char>,std::allocator<char>>&") {
70 return "const std::string&";
71 } else {
72 return std::string{type_name};
73 }
74}
75
76#if HI_COMPILER == HI_CC_MSVC
77template<typename T>
78[[nodiscard]] constexpr std::string type_name() noexcept
79{
80 // "std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > __cdecl hi::v1::type_name<T>(void)
81 // noexcept"
82 auto signature = std::string_view{__FUNCSIG__};
83
84 // Extract the type passed to type_name().
85 auto first = signature.find("type_name<");
86 hi_assert(first != std::string_view::npos);
87 first += 10;
88
89 auto last = signature.rfind('>');
90 hi_assert(last != std::string_view::npos);
91
92 signature = signature.substr(first, last - first);
93
94 auto r = std::string{};
95 while (not signature.empty()) {
96 if (signature.starts_with("class ")) {
97 signature = signature.substr(6);
98 } else if (signature.starts_with("struct ")) {
99 signature = signature.substr(7);
100 } else if (signature.starts_with(" >")) {
101 r += '>';
102 signature = signature.substr(2);
103 } else if (signature.starts_with(" *")) {
104 r += '*';
105 signature = signature.substr(2);
106 } else {
107 auto token = type_name_token(signature);
108 r += token;
109 signature = signature.substr(token.size());
110 }
111 }
112
113 return type_name_short_hand(r);
114}
115#else
116#error "_type_name() not implemented for this compiler."
117#endif
118
119} // namespace detail
120
121template<typename T>
122struct number_of_data_members : std::integral_constant<size_t, detail::count_data_members<T>()> {};
123
124template<typename T>
125constexpr size_t number_of_data_members_v = number_of_data_members<T>::value;
126
127template<size_t Index, typename Type>
128constexpr decltype(auto) get_data_member(Type&& rhs) noexcept
129{
130#define HI_X_FORWARD(x) forward_like<Type>(x),
131
132 constexpr auto number_of_members = number_of_data_members<std::remove_cvref_t<Type>>();
133
134 if constexpr (number_of_members == 0) {
136
137 // clang-format off
138#define HI_X(count, ...) \
139 } else if constexpr (number_of_members == count) { \
140 auto&& [__VA_ARGS__] = rhs; \
141 return std::get<Index>(std::forward_as_tuple(hi_for_each(HI_X_FORWARD, __VA_ARGS__) 0));
142
143 HI_X( 1, a)
144 HI_X( 2, a,b)
145 HI_X( 3, a,b,c)
146 HI_X( 4, a,b,c,d)
147 HI_X( 5, a,b,c,d,e)
148 HI_X( 6, a,b,c,d,e,f)
149 HI_X( 7, a,b,c,d,e,f,g)
150 HI_X( 8, a,b,c,d,e,f,g,h)
151 HI_X( 9, a,b,c,d,e,f,g,h,i)
152 HI_X(10, a,b,c,d,e,f,g,h,i,j)
153 HI_X(11, a,b,c,d,e,f,g,h,i,j,k)
154 HI_X(12, a,b,c,d,e,f,g,h,i,j,k,l)
155 HI_X(13, a,b,c,d,e,f,g,h,i,j,k,l,m)
156 HI_X(14, a,b,c,d,e,f,g,h,i,j,k,l,m,n)
157 HI_X(15, a,b,c,d,e,f,g,h,i,j,k,l,m,n,o)
158 HI_X(16, a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p)
159 HI_X(17, a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q)
160 HI_X(18, a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r)
161 HI_X(19, a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s)
162 HI_X(20, a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t)
163 HI_X(21, a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u)
164 HI_X(22, a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v)
165 HI_X(23, a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w)
166 HI_X(24, a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x)
167 HI_X(25, a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y)
168 HI_X(26, a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z)
169 HI_X(27, a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z,A)
170 HI_X(28, a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z,A,B)
171 HI_X(29, a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z,A,B,C)
172 HI_X(30, a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z,A,B,C,D)
173 HI_X(31, a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z,A,B,C,D,E)
174 HI_X(32, a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z,A,B,C,D,E,F)
175 HI_X(33, a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z,A,B,C,D,E,F,G)
176 HI_X(34, a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z,A,B,C,D,E,F,G,H)
177 HI_X(35, a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z,A,B,C,D,E,F,G,H,I)
178 HI_X(36, a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z,A,B,C,D,E,F,G,H,I,J)
179 HI_X(37, a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z,A,B,C,D,E,F,G,H,I,J,K)
180 HI_X(38, a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z,A,B,C,D,E,F,G,H,I,J,K,L)
181 HI_X(39, a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z,A,B,C,D,E,F,G,H,I,J,K,L,M)
182 HI_X(40, a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z,A,B,C,D,E,F,G,H,I,J,K,L,M,N)
183 HI_X(41, a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z,A,B,C,D,E,F,G,H,I,J,K,L,M,N,O)
184 HI_X(42, a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z,A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P)
185 HI_X(43, a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z,A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q)
186 HI_X(44, a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z,A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R)
187 HI_X(45, a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z,A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S)
188 HI_X(46, a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z,A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T)
189 HI_X(47, a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z,A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U)
190 HI_X(48, a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z,A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V)
191 HI_X(49, a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z,A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W)
192 HI_X(50, a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z,A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X)
193 HI_X(51, a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z,A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y)
194 HI_X(52, a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z,A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z)
195 // clang-format on
196
197 } else {
199 }
200
201#undef HI_X
202#undef HI_X_FORWARD
203}
204
205template<typename T>
206[[nodiscard]] constexpr auto type_name() noexcept
207{
208 return hi_to_fixed_string(detail::type_name<T>());
209}
210
211}} // namespace hi::v1
#define hi_static_no_default(...)
This part of the code should not be reachable, unless a programming bug.
Definition assert.hpp:323
#define hi_assert(expression,...)
Assert if expression is true.
Definition assert.hpp:199
#define hi_static_not_implemented(...)
This part of the code has not been implemented yet.
Definition assert.hpp:342
#define hilet
Invariant should be the default for variables.
Definition utility.hpp:23
DOXYGEN BUG.
Definition algorithm.hpp:13
geometry/margins.hpp
Definition cache.hpp:11
A type that can be implicitly converted to any type.
Definition reflection.hpp:16
Definition reflection.hpp:122
T find(T... args)
T substr(T... args)