MSTL 1.4.0
A Modern C++ Library with extended functionality, web components, and utility libraries
载入中...
搜索中...
未找到
check_type.hpp
1#ifndef MSTL_CORE_TYPEINFO_CHECK_TYPE_HPP__
2#define MSTL_CORE_TYPEINFO_CHECK_TYPE_HPP__
3#include "../utility/packages.hpp"
4#ifdef MSTL_COMPILER_GNUC__
5#include <cxxabi.h>
6#include <cstdlib> // std::free
7#endif // MSTL_COMPILER_GNUC__
10
11class output {
12private:
13 bool is_compact_;
14 string& sr_;
15
16 template <typename T>
17 static MSTL_CONSTEXPR20 bool check_empty(const T&) { return false; }
18 static MSTL_CONSTEXPR20 bool check_empty(const char* val) { return !val || val[0] == 0; }
19
20 template <typename T>
21 MSTL_CONSTEXPR20 void out(const T& val) {
22 if (this->check_empty(val)) return;
23 if (!this->is_compact_) sr_ += " ";
24 this->sr_ += to_string(val);
25 this->is_compact_ = false;
26 }
27
28public:
29 MSTL_CONSTEXPR20 output(string& sr) : is_compact_(true), sr_(sr) {}
30 MSTL_CONSTEXPR20 output& operator ()() { return *this; }
31 MSTL_CONSTEXPR20 output& compact(){
32 this->is_compact_ = true;
33 return *this;
34 }
35
36 template <typename T1, typename... T>
37 MSTL_CONSTEXPR20 output& operator ()(const T1& val, const T&... args) {
38 this->out(val);
39 return operator ()(args...);
40 }
41};
42
43template <bool>
44struct bracket { // ()
45 output& out_;
46 MSTL_CONSTEXPR20 bracket(output& out, const char* = nullptr) : out_(out) {
47 out_("(").compact();
48 }
49 MSTL_CONSTEXPR20 ~bracket() {
50 out_.compact()(")");
51 }
52};
53template <>
54struct bracket<false> {
55 MSTL_CONSTEXPR20 bracket(output& out, const char* str = nullptr) { out(str); }
56};
57
58template <size_t N = 0>
59struct bound { // [N]
60private:
61 template <size_t NN, enable_if_t<NN == 0, int> = 0>
62 MSTL_CONSTEXPR20 void __bound_dispatch() const { out_("[]"); }
63 template <size_t NN, enable_if_t<NN != 0, int> = 0>
64 MSTL_CONSTEXPR20 void __bound_dispatch() const { out_("[").compact()(NN).compact()("]"); }
65
66public:
67 output& out_;
68
69 MSTL_CONSTEXPR20 bound(output& out) : out_(out) {}
70 MSTL_CONSTEXPR20 ~bound() {
71 __bound_dispatch<N>();
72 }
73};
74
75template <bool, typename... P>
76struct parameter; // parameter
77
78template <bool IsStart>
79struct parameter<IsStart> {
80 output& out_;
81
82 MSTL_CONSTEXPR20 parameter(output& out) : out_(out) {}
83 MSTL_CONSTEXPR20 ~parameter() { bracket<IsStart> { out_ }; }
84};
85
86
87template <typename T, bool IsBase = false>
88struct check {
89 output out_;
90
91 MSTL_CONSTEXPR20 check(const output& out) : out_(out) {
92#ifdef MSTL_COMPILER_GNUC__
93 auto deleter = [](char* p) { if (p) std::free(p); };
95 _MSTL unique_ptr<char, decltype(deleter)> real_name {
96 ::abi::__cxa_demangle(typeid(FinT).name(), nullptr, nullptr, nullptr), deleter
97 };
98 out_(real_name.get());
99#else
100 out_(typeid(T).name());
101#endif
102 }
103};
104
105template <typename T, bool IsBase>
106struct check<T[], IsBase> : check<T, true> { // array
107 using base_t = check<T, true>;
108 using base_t::out_;
109 bound<> bound_;
110 bracket<IsBase> bracket_;
111
112 MSTL_CONSTEXPR20 check(const output& out) : base_t(out), bound_(out_), bracket_(out_) {}
113};
114
115#define CHECK_TYPE__(OPT) \
116 template <typename T, bool IsBase> \
117 struct check<T OPT, IsBase> : check<T, true> { \
118 using base_t = check<T, true>; \
119 using base_t::out_; \
120 MSTL_CONSTEXPR20 check(const output& out) : base_t(out) { out_(#OPT); } \
121 };
122
123CHECK_TYPE__(const)
124CHECK_TYPE__(volatile)
125CHECK_TYPE__(const volatile)
126CHECK_TYPE__(&)
127CHECK_TYPE__(&&)
128CHECK_TYPE__(*)
129#undef CHECK_TYPE__
130
131
132template <bool IsStart, typename P1, typename... P>
133struct parameter<IsStart, P1, P...> {
134 output& out_;
135 MSTL_CONSTEXPR20 parameter(output& out) : out_(out) {}
136 MSTL_CONSTEXPR20 ~parameter() {
137 [this](bracket<IsStart>&&) {
138 check<P1> { out_ };
139 parameter<false, P...> { out_.compact() };
140 } (bracket<IsStart> { out_, "," });
141 }
142};
143
144#define CHECK_TYPE_ARRAY__(CV_OPT, BOUND_OPT, ...) \
145 template <typename T, bool IsBase __VA_ARGS__> \
146 struct check<T CV_OPT [BOUND_OPT], IsBase> : check<T CV_OPT, !is_array_v<T>> { \
147 using base_t = check<T CV_OPT, !is_array_v<T>>; \
148 using base_t::out_; \
149 bound<BOUND_OPT> bound_; \
150 bracket<IsBase> bracket_; \
151 MSTL_CONSTEXPR20 check(const output& out) : base_t(out) \
152 , bound_ (out_) \
153 , bracket_(out_) \
154 {} \
155 };
156
157#define CHECK_TYPE_ARRAY_CV__(BOUND_OPT, ...) \
158 CHECK_TYPE_ARRAY__(, BOUND_OPT, ,##__VA_ARGS__) \
159 CHECK_TYPE_ARRAY__(const, BOUND_OPT, ,##__VA_ARGS__) \
160 CHECK_TYPE_ARRAY__(volatile, BOUND_OPT, ,##__VA_ARGS__) \
161 CHECK_TYPE_ARRAY__(const volatile, BOUND_OPT, ,##__VA_ARGS__)
162
163#ifdef MSTL_COMPILE_GNUC__
164CHECK_TYPE_ARRAY_CV__(0)
165#endif
166CHECK_TYPE_ARRAY_CV__(N, size_t N)
167CHECK_TYPE_ARRAY__(const, , )
168CHECK_TYPE_ARRAY__(volatile, , )
169CHECK_TYPE_ARRAY__(const volatile, , )
170
171#undef CHECK_TYPE_ARRAY__
172#undef CHECK_TYPE_ARRAY_CV__
173
174template <typename T, bool IsBase, typename... P>
175struct check<T(P...), IsBase> : check<T, true> { // function
176 using base_t = check<T, true>;
177 using base_t::out_;
178 parameter<true, P...> parameter_;
179 bracket<IsBase> bracket_;
180
181 MSTL_CONSTEXPR20 check(const output& out)
182 : base_t(out), parameter_(out_), bracket_(out_) {}
183};
184
185template <typename T, bool IsBase, typename C>
186struct check<T C::*, IsBase> : check<T, true> { // member function
187 using base_t = check<T, true>;
188 using base_t::out_;
189
190 MSTL_CONSTEXPR20 check(const output& out) : base_t(out) {
191 check<C> { out_ };
192 out_.compact()("::*");
193 }
194};
195
196template <typename T, bool IsBase, typename C, typename... P>
197struct check<T(C::*)(P...), IsBase> : check<T(P...), true> { // member object function
198 using base_t = check<T(P...), true>;
199 using base_t::out_;
200
201 MSTL_CONSTEXPR20 check(const output& out) : base_t(out) {
202 check<C> { out_ };
203 out_.compact()("::*");
204 }
205};
206
207struct at_destruct {
208 output& out_;
209 const char* str_;
210
211 MSTL_CONSTEXPR20 at_destruct(output& out, const char* str = nullptr): out_(out), str_(str) {}
212 MSTL_CONSTEXPR20 ~at_destruct() { out_(str_); }
213 MSTL_CONSTEXPR20 void set_str(const char* str = nullptr) { str_ = str; }
214};
215
216#define CHECK_TYPE_MEM_FUNC__(...) \
217 template <typename T, bool IsBase, typename C, typename... P> \
218 struct check<T(C::*)(P...) __VA_ARGS__, IsBase> { \
219 at_destruct cv_; \
220 check<T(P...), true> base_; \
221 output& out_ = base_.out_; \
222 MSTL_CONSTEXPR20 check(const output& out) \
223 : cv_(base_.out_), base_(out) { \
224 cv_.set_str(#__VA_ARGS__); \
225 check<C> { out_ }; \
226 out_.compact()("::*"); \
227 } \
228 };
229
230CHECK_TYPE_MEM_FUNC__(const)
231CHECK_TYPE_MEM_FUNC__(volatile)
232CHECK_TYPE_MEM_FUNC__(const volatile)
233#undef CHECK_TYPE_MEM_FUNC__
234
236
237template <typename T>
238MSTL_CONSTEXPR20 string check_type() {
239 string str;
240 _INNER check<T> { str };
241 return str;
242}
243
245#endif // MSTL_CORE_TYPEINFO_CHECK_TYPE_HPP__
#define _MSTL
全局命名空间MSTL前缀
#define MSTL_END_INNER__
结束inner命名空间
#define _INNER
inner命名空间前缀
#define MSTL_END_NAMESPACE__
结束全局命名空间MSTL
#define MSTL_BEGIN_NAMESPACE__
开始全局命名空间MSTL
#define MSTL_BEGIN_INNER__
开始inner命名空间
typename remove_function_qualifiers< T >::type remove_function_qualifiers_t
remove_function_qualifiers的便捷别名