Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <iostream>
- #include <vector>
- #include <string>
- using std::string;
- /*
- These macros define a struct with an implicitly defined Show function that visits each member.
- The trick is that a typedef is split between each STRUCT_MEMBER instance and the preceding macro,
- which allows it to define an empty struct type that identifies the following struct member, while also
- knowing the struct type that the preceding macro is using to identify the current member.
- It defines a _ShowMembersFollowing function that is overloaded for the empty struct type identifying
- the current member to show the current member, then call _ShowMembersFollow with the struct type
- identifying the following member.
- */
- #define BEGIN_STRUCT(StructName) \
- class StructName \
- { \
- public: \
- friend string Show(const StructName& Struct,const string& LineSeparator = "\n") \
- { \
- /* Generate the struct: prefix and call the overloaded _ShowMembersFollowing with the empty struct identifying the first member. */ \
- return "struct:" + _ShowMembersFollowing(_FirstMemberId(),LineSeparator + "\t",Struct); \
- } \
- private: \
- typedef StructName _ThisStruct; \
- /* Define an empty struct that will identify the first member. The ID is passed to the following macro by a partial typedef declaration. */ \
- struct _FirstMemberId {}; \
- typedef _FirstMemberId
- #define STRUCT_MEMBER(MemberType, MemberName) \
- /* Complete the typedef provided by the previous macro with an alias for this member's ID. */ \
- _MemberId_##MemberName; \
- public: \
- MemberType MemberName; \
- private: \
- /* Define an empty struct that will identify the next member. */ \
- struct _NextMemberId_##MemberName {}; \
- /* Overload the _ShowMembersFollowing function for this member's ID. */ \
- static string _ShowMembersFollowing(_MemberId_##MemberName, const string& LineSeparator, const _ThisStruct& Struct) \
- { \
- /* Show this member and recursively call _ShowMembersFollowing for the struct identifying the following member. */ \
- return LineSeparator + #MemberName + " = " \
- + ::Show(Struct.MemberName,LineSeparator) \
- + _ShowMembersFollowing(_NextMemberId_##MemberName(), LineSeparator, Struct); \
- } \
- /* Begin a typedef for the next member's identifying struct; use the _NextMemberId_x struct defined in this macro, */ \
- /* but leave it incomplete so the next macro can provide the name it will use to reference the ID. */ \
- typedef _NextMemberId_##MemberName
- #define END_STRUCT(StructName) \
- /* Complete the typedef provided by the previous macro with an alias for this member's ID. */ \
- _LastMemberId; \
- static string _ShowMembersFollowing(_LastMemberId, const string&, const _ThisStruct&) { return ""; } \
- };
- // Shows an integer.
- string Show(int Int,const string& LineSeparator = "\n") { return std::to_string(Int); }
- // Shows a vector.
- template<typename ElementType> string Show(const std::vector<ElementType>& Vector,const string& LineSeparator = "\n")
- {
- string Result;
- Result += "array:";
- for(auto ElementIt = Vector.begin();ElementIt < Vector.end();++ElementIt)
- {
- Result += LineSeparator + "\t";
- Result += Show(*ElementIt,LineSeparator + "\t");
- }
- return Result;
- }
- BEGIN_STRUCT(A)
- STRUCT_MEMBER(int,intMember1)
- STRUCT_MEMBER(int,intMember2)
- END_STRUCT(A)
- BEGIN_STRUCT(B)
- STRUCT_MEMBER(std::vector<A>,arrayMember)
- END_STRUCT(B)
- void main()
- {
- A a1 = {1,2};
- A a2 = {4,3};
- B b;
- b.arrayMember.push_back(a1);
- b.arrayMember.push_back(a2);
- std::cout << Show(b);
- /*
- struct:
- arrayMember = array:
- struct:
- intMember1 = 1
- intMember2 = 2
- struct:
- intMember1 = 4
- intMember2 = 3
- */
- }
Add Comment
Please, Sign In to add comment