其他
C++ 反射:第三章 原生
The following article is from CPP编程客 Author 里缪
工具能够提升开发效率,却也会限制住思维。
基本Introspection
#include <string>
struct person {
int age;
std::string name;
};
template<typename T>
void print_members() {
std::cout << @type_string(T) << ":\n";
@meta for(int i = 0; i < @member_count(T); ++i) {
std::cout << i << " " << @member_type_string(T, i)
<< " " << @member_name(T, i) << "\n";
}
}
int main() {
print_members<person>();
}
person:
0 int age
1 std::string name
void print_members() {
std::cout << @type_string(T) << ":\n";
(std::cout << int... << " " << @member_type_strings(T)
<< @member_names(T) << "\n")...;
}
public: float x;
protected: float y;
private: float z;
};
int main() {
//print_members<person>();
//print_enumerations<Days>();
(std::cout << int... << ": " << @member_decl_strings(pointer, 1) << "\n---\n")...;
(std::cout << int... << ": " << @member_decl_strings(pointer, 2) << "\n---\n")...;
(std::cout << int... << ": " << @member_decl_strings(pointer, 4) << "\n")...;
}
---
0: float y
---
0: float z
Monday = 1,
Tuesday,
Wednesday,
Thursday,
Friday,
Saturday,
Sunday
};
template<typename Enum>
requires std::is_enum_v<Enum>
std::string enum_to_string(Enum value) {
switch(value) {
@meta for enum(Enum e : Enum) {
case e:
return @enum_name(e);
}
default:
return "<unnamed>";
}
}
template<typename Enum>
void print_enumerations() {
std::cout << @type_string(Enum) << ":\n";
(std::cout << int... << ": " << enum_to_string(@enum_values(Enum)) << '\n')...;
}
int main() {
//print_members<person>();
print_enumerations<Days>();
}
Days:
0: Monday
1: Tuesday
2: Wednesday
3: Thursday
4: Friday
5: Saturday
6: Sunday
void print_enumerations() {
std::cout << @type_string(Enum) << ":\n";
(std::cout << int... << ": " << @enum_name(@enum_values(Enum)) << '\n')...;
}
std::optional<Enum> string_to_enum(const char* s) {
@meta for enum(Enum e : Enum) {
if(0 == strcmp(@enum_name(e), s))
return e;
}
return { };
}
int main() {
//print_members<person>();
//print_enumerations<Days>();
auto value = string_to_enum<Days>("Sunday");
assert(*value == Days::Sunday);
}
自定义Attributes
using color [[attribute]] = const char*;
using country [[attribute]] = const char*;
struct book {
[[.color="red"]] std::string title;
[[.country="China"]] std::string author;
int page_count;
};
int main() {
// print_members<person>();
// print_enumerations<Days>();
// (std::cout << int... << ": " << @member_decl_strings(pointer, 1) << "\n---\n")...;
// (std::cout << int... << ": " << @member_decl_strings(pointer, 2) << "\n---\n")...;
// (std::cout << int... << ": " << @member_decl_strings(pointer, 4) << "\n")...;
book b;
std::cout << @attribute(b.@member_value(0), color); // output: red
std::cout << @attribute(b.@member_value(1), country); // output: China
}
using attrib-name [[attribute]] = typename;
enum class Days {
Monday = 1,
Tuesday,
Wednesday,
Thursday,
Friday,
Saturday [[.vacation="true"]],
Sunday [[.vacation="true"]]
};
template<typename Enum>
requires std::is_enum_v<Enum>
std::string enum_to_string(Enum value) {
switch(value) {
@meta for enum(Enum e : Enum) {
case e:
if constexpr (@enum_has_attribute(e, vacation))
return @enum_attribute(e, vacation);
else
return @enum_name(e);
}
default:
return "<unnamed>";
}
}
int main() {
// print_members<person>();
// print_enumerations<Days>();
// (std::cout << int... << ": " << @member_decl_strings(pointer, 1) << "\n---\n")...;
// (std::cout << int... << ": " << @member_decl_strings(pointer, 2) << "\n---\n")...;
// (std::cout << int... << ": " << @member_decl_strings(pointer, 4) << "\n")...;
// book b;
// std::cout << @attribute(b.@member_value(0), color); // output: red
// std::cout << @attribute(b.@member_value(1), country); // output: China
(std::cout << enum_to_string(@enum_values(Days)) << "\n---\n")...;
}
---
Tuesday
---
Wednesday
---
Thursday
---
Friday
---
true
---
true
---
Typed enums
int,
double,
char*,
char,
std::string
};
template<typename type_t>
void print_typed_enum() {
std::cout << @type_string(type_t) << '\n';
(std::cout << int... << ": " << @enum_type_strings(type_t) << '\n')...;
}
0: int
1: double
2: char*
3: char
4: std::string
float;
int[5];
// 使用包展开定义类型
@enum_types(type_list)...;
// 逆序展开
@enum_types(type_list)...[::-1] ...;
};
0: float
1: int[5]
2: int
3: double
4: char*
5: char
6: std::string
7: std::string
8: char
9: char*
10: double
11: int
@meta std::array types {
std::make_pair<std::string, int>(
@enum_type_strings(type_list_join),
int...
)...
};
@meta std::sort(types.begin(), types.end());
@enum_type(type_list_join, @pack_nontype(types).second) ...;
};
0: char
1: char
2: char*
3: char*
4: double
5: double
6: float
7: int
8: int
9: int[5]
10: std::string
11: std::string
void print_types() {
@meta for typename(type_t : { types... }) {
std::cout << @type_string(type_t) << '\n';
}
}
template<typename type_list>
void print_typed_enum() {
// std::cout << @type_string(type_t) << '\n';
// (std::cout << int... << ": " << @enum_type_strings(type_t) << '\n')...;
@meta for typename(type_t : enum type_list)
std::cout << @type_string(type_t) << '\n';
}
print_types<int, char, float, double, std::string>();
print_typed_enum<sorted_type_list>();
动态命名
struct tuple_t {
const char* @("var");
type_t @(int...) ...;
};
// 遍历所有定义成员全称
@meta puts(@member_decl_strings(tuple_t<int, char, double>))...;
int _0;
char _1;
double _2;
动态生成类
@meta j["types"]["name"] = "person";
@meta j["types"]["members"] = { {{"name", "age"}, {"type", "int"}},
{{"name", "name"},{"type", "std::string"}} };
"types": {
"members": [
{
"name": "age",
"type": "int"
},
{
"name": "name",
"type": "std::string"
}
],
"name": "person"
}
}
@meta struct @(types["name"]) {
@meta for(json& members : types["members"]) {
@type_id(members["type"]) @(members["name"]);
}
};
enum typename type_list {
@type_id(types["name"]);
};
int main() {
@meta for typename(type_t : enum type_list) {
std::cout << "struct " << @type_string(type_t) << "{\n";
(std::cout << @member_decl_strings(type_t) << ";\n")...;
std::cout << "};\n";
}
}
总结
- EOF -
加主页君微信,不仅C/C++技能+1
主页君日常还会在个人微信分享C/C++开发学习资源和技术文章精选,不定期分享一些有意思的活动、岗位内推以及如何用技术做业余项目
加个微信,打开一扇窗
关注『CPP开发者』
看精选C/C++技术文章
点赞和在看就是最大的支持❤️