Run Code
|
API
|
Code Wall
|
Misc
|
Feedback
|
Login
|
Theme
|
Privacy
|
Patreon
define_xml_tags
#include <iostream> #include <boost/fusion/include/io.hpp> #include <boost/fusion/include/as_vector.hpp> #include <boost/variant/static_visitor.hpp> //beginning of define_xml_tags.hpp #include <boost/fusion/include/define_struct.hpp> #include <boost/variant.hpp> #include <vector> #include <utility> #include <boost/preprocessor/cat.hpp> #include <boost/preprocessor/repetition/repeat.hpp> #include <boost/preprocessor/seq/enum.hpp> #include <boost/preprocessor/seq/for_each.hpp> #include <boost/preprocessor/seq/for_each_i.hpp> #include <boost/preprocessor/seq/size.hpp> #include <boost/preprocessor/stringize.hpp> #include <boost/preprocessor/tuple/elem.hpp> //I think there is a bug in the original macro, it uses BOOST_PP_REPEAT_1 where I think it should use BOOST_PP_REPEAT, but I don't know enough to know for sure #undef BOOST_FUSION_ADAPT_STRUCT_NAMESPACE_DEFINITION_END #define BOOST_FUSION_ADAPT_STRUCT_NAMESPACE_DEFINITION_END(NAMESPACE_SEQ) \ BOOST_PP_REPEAT( \ BOOST_PP_DEC(BOOST_PP_SEQ_SIZE(NAMESPACE_SEQ)), \ BOOST_FUSION_ADAPT_STRUCT_NAMESPACE_END_I, \ _) //helps form a SEQUENCE of TUPLES #define XML_TAG_1(NAME) ((NAME,(std::string,name))) #define XML_TAG_2(NAME,MEMBER_SEQ) ((NAME,(std::string,name)MEMBER_SEQ)) #if !BOOST_PP_VARIADICS_MSVC #define XML_TAG(...) BOOST_PP_OVERLOAD(XML_TAG_,__VA_ARGS__)(__VA_ARGS__) #else // or for Visual C++ #define XML_TAG(...) \ BOOST_PP_CAT(BOOST_PP_OVERLOAD(XML_TAG_,__VA_ARGS__)(__VA_ARGS__),BOOST_PP_EMPTY()) #endif //helpers for GENERATE_STRUCT_DEFS, read from the bottom to the top #define DO_GENERATE_ONE_STRUCT_DEF(NAME,MEMBER_SEQ) \ BOOST_FUSION_DEFINE_STRUCT( (), NAME, MEMBER_SEQ) #define GENERATE_ONE_STRUCT_DEF(Z,INDEX,TAG_SEQ) \ DO_GENERATE_ONE_STRUCT_DEF(BOOST_PP_TUPLE_ELEM(2,0,BOOST_PP_SEQ_ELEM(INDEX,TAG_SEQ)), BOOST_PP_TUPLE_ELEM(2,1,BOOST_PP_SEQ_ELEM(INDEX,TAG_SEQ))) #define GENERATE_STRUCT_DEFS(TAG_SEQ) \ BOOST_PP_REPEAT(BOOST_PP_SEQ_SIZE(TAG_SEQ),GENERATE_ONE_STRUCT_DEF,TAG_SEQ) //helpers for GENERATE_VARIANT_OF_TYPES, bottom to top #define GET_TYPE_SEQUENCE(R,DATA,NAME_MEMBERSEQ_TUPLE) \ (BOOST_PP_TUPLE_ELEM(2,0,NAME_MEMBERSEQ_TUPLE)) #define ENUMERATE_TYPES(TAG_SEQ) \ BOOST_PP_SEQ_ENUM(BOOST_PP_SEQ_FOR_EACH(GET_TYPE_SEQUENCE,_,TAG_SEQ)) #define GENERATE_VARIANT_OF_TYPES(TAG_SEQ) \ typedef boost::variant<ENUMERATE_TYPES(TAG_SEQ)> Types; //helpers for GENERATE_XMLTAGS, go from bottom to top in order to understand //Heavily "inspired" from BOOST_FUSION_ADAPT_STRUCT #define GENERATE_NAME_SEQUENCE_FILLER_0(X, Y) \ ((X, Y)) GENERATE_NAME_SEQUENCE_FILLER_1 #define GENERATE_NAME_SEQUENCE_FILLER_1(X, Y) \ ((X, Y)) GENERATE_NAME_SEQUENCE_FILLER_0 #define GENERATE_NAME_SEQUENCE_FILLER_0_END #define GENERATE_NAME_SEQUENCE_FILLER_1_END #define GENERATE_MEMBER_NAME_SEQUENCE(R,DATA,INDEX,TYPE_NAME_TUPLE) (BOOST_PP_STRINGIZE(BOOST_PP_TUPLE_ELEM(2,1,TYPE_NAME_TUPLE))) #define GENERATE_VECTOR_OF_MEMBER_NAMES(MEMBER_SEQ) \ { BOOST_PP_SEQ_ENUM(BOOST_PP_SEQ_FOR_EACH_I(GENERATE_MEMBER_NAME_SEQUENCE,_,BOOST_PP_CAT(GENERATE_NAME_SEQUENCE_FILLER_0 MEMBER_SEQ,_END))) } #define GENERATE_ONE_PAIR(R,DATA,NAME_MEMBERSEQ_TUPLE) \ { BOOST_PP_TUPLE_ELEM(2,0,NAME_MEMBERSEQ_TUPLE)(), GENERATE_VECTOR_OF_MEMBER_NAMES(BOOST_PP_TUPLE_ELEM(2,1,NAME_MEMBERSEQ_TUPLE)) }, #define GENERATE_PAIRS(TAG_SEQ) \ BOOST_PP_SEQ_FOR_EACH(GENERATE_ONE_PAIR,_,TAG_SEQ) #define GENERATE_XMLTAGS(TAG_SEQ) \ const std::vector<std::pair<Types,std::vector<std::string>>> xmlTags = { GENERATE_PAIRS(TAG_SEQ) }; //This is the actual macro, it simply invokes three different macros that do a different task each #define DEFINE_XML_TAGS(TAG_SEQ) \ GENERATE_STRUCT_DEFS(TAG_SEQ) \ GENERATE_VARIANT_OF_TYPES(TAG_SEQ) \ GENERATE_XMLTAGS(TAG_SEQ) //end of define_xml_tags.hpp DEFINE_XML_TAGS( XML_TAG( Person, (int, age) ) XML_TAG( Company, (int, noEmployees) (std::string, location) ) XML_TAG(Container) ) struct printer : boost::static_visitor<void> { void operator()(const Person& p) const { std::cout << "This is a person:" << boost::fusion::as_vector(p) << '\n'; } void operator()(const Company& c) const { std::cout << "This is a company:" << boost::fusion::as_vector(c) << '\n'; } void operator()(const Container& c) const { std::cout << "This is a container:" << boost::fusion::as_vector(c) << '\n'; } }; void identify(Types v) { boost::apply_visitor(printer(),v); } int main() { Person p; p.name="John"; p.age = 18; identify(p); Company c; c.name="Mpany Co"; c.noEmployees=123; c.location="Fake St"; identify(c); std::cout << "\nChecking xmlTags:\n"; for(const auto& pair : xmlTags) { identify(pair.first); std::cout << "It has the following members:\n"; for(const auto& str : pair.second) std::cout << str << '\n'; } std::cout << std::endl; }
run
|
edit
|
history
|
help
0
Type deduction in VC++
div64 inline asm
return reference (msvc)
Regex failure
C++ move/copy constructor and assignment demo
base call virtual
Default constructor - deleted
wrong up
VS2013 hello world includes
enable_if::type