दिलचस्प पोस्ट
Gnuplot लाइन प्रकार उद्देश्य-सी में स्ट्रिंग की तुलना सर्वोच्च आवंटित फ़ाइल डिस्क्रिप्टर प्राप्त करना iFrame एसआरसी परिवर्तन घटना का पता लगाने? * प्रत्येक * आइटम सूची में Django फ़िल्टर क्वेरीसेट __in के लिए एक सामान्य संपत्ति बनाना एमएस एक्सेस एप्लिकेशन का परीक्षण करने का सर्वोत्तम तरीका है? श्रृंखलन कार्य कैसे काम करते हैं? क्या आईफोन / एंड्रॉइड एप्लीकेशन विकसित करने के लिए एक मल्टीप्लेफ़्ट फ्रेमवर्क है? JQuery के उपयोग से वर्ग परिवर्तन पर एक घटना को कैसे आग लगा सकता है? कार्य टास्क हर एक्स मिनट के साथ विंडोज टास्क समयबद्धक आईओएस 6 फेसबुक पोस्टिंग की प्रक्रिया को समाप्त होता है "रिमोटमैप_आईडी संग्रहीत आईडी से मेल नहीं खाता" मैं सीएसएस में पृष्ठभूमि छवियों को कैसे प्रिंट करूं? JQuery का उपयोग करना – सबमिट करने से फॉर्म को रोकना सीएसएस का इस्तेमाल करते हुए माता-पिता डीआईवी की तुलना में बाल DIV की चौड़ाई व्यापक बनाने का तरीका क्या है?

सी + + प्रीप्रोसेसर: सदस्य चर सूची का कोड पुनरावृत्ति से बचें

मेरे पास एक अलग वर्ग के सदस्य होते हैं जिनमें अलग-अलग सदस्य चर का निर्माण होता है जो कंसक्टर के रूप में शुरू हो जाते हैं। यहाँ एक उदाहरण है:

struct Person { Person(const char *name, int age) : name(name), age(age) { } private: const char *name; int age; }; 

प्रत्येक का एक संबद्ध print<>() फ़ंक्शन है।

 template <> void print<Person>(const Person &person) { std::cout << "name=" << name << "\n"; std::cout << "age=" << age << "\n"; } 

यह कोड त्रुटि प्रवण है क्योंकि पैरामीटर सूची को चार स्थानों में दोहराया गया है। मैं इस दोहराव से बचने के लिए कोड को फिर से कैसे लिख सकता हूं? मैं पूर्वप्रोसेसर और / या टेम्पलेट्स का उपयोग करना चाहता हूं।

उदाहरण के लिए, क्या मैं एक्स-आरजीएस प्रीप्रोसेसर तकनीक का उपयोग कर सकता हूं – ऐसा कुछ?

 #define ARGUMENTS \ ARG(const char *, name) \ ARG(int, age) struct Person { Person(LIST_TYPE_NAME_COMMA(ARGUMENTS)) : LIST_NAME_INIT(ARGUMENTS) { } private: LIST_TYPE_NAME_SEMICOLON(ARGUMENTS) }; template <> void print<Person>(const Person &person) { LIST_COUT_LINE(ARGUMENTS) } #undef ARGUMENTS 

या बेहतर, एक टेम्पलेट आधारित दृष्टिकोण?

कृपया ऐसा सवाल न करें कि मैं ऐसा क्यों करना चाहता हूं, डिज़ाइन निर्णयों के कारण तर्कसंगत हैं, जिनके फलस्वरूप नाममात्र पैरामीटर वाले एक से अधिक समान वस्तुएं हैं। प्रदर्शन के कारणों के लिए पैरामीटर को सदस्य चर नामित करने की आवश्यकता है मैं बस यह खोज रहा हूं कि क्या पैरामीटर और उनके प्रकार की सूची केवल एक बार संभव है या नहीं।

वेब के समाधान से एकत्रित समाधान "सी + + प्रीप्रोसेसर: सदस्य चर सूची का कोड पुनरावृत्ति से बचें"

आपको क्या करने की ज़रूरत है, फ़ील्ड के बारे में पूर्वप्रक्रमक प्रतिबिंब डेटा उत्पन्न करता है यह डेटा नेस्टेड कक्षाओं के रूप में संग्रहीत किया जा सकता है।

सबसे पहले, इसे आसान बनाने के लिए और इसे प्रीप्रोसेसर में लिखने के लिए क्लीनर, हम टाइप किए गए अभिव्यक्ति का उपयोग करेंगे टाइप किया गया अभिव्यक्ति सिर्फ एक अभिव्यक्ति है जो कोष्ठक में टाइप करता है इसलिए int x लिखने के बजाय आप (int) x लिखेंगे टाइप एक्सप्रेशंस के साथ मदद करने के लिए यहां कुछ आसान मैक्रोज़ हैं:

 #define REM(...) __VA_ARGS__ #define EAT(...) // Retrieve the type #define TYPEOF(x) DETAIL_TYPEOF(DETAIL_TYPEOF_PROBE x,) #define DETAIL_TYPEOF(...) DETAIL_TYPEOF_HEAD(__VA_ARGS__) #define DETAIL_TYPEOF_HEAD(x, ...) REM x #define DETAIL_TYPEOF_PROBE(...) (__VA_ARGS__), // Strip off the type #define STRIP(x) EAT x // Show the type without parenthesis #define PAIR(x) REM x 

इसके बाद, हम प्रत्येक फ़ील्ड (और फ़ील्ड ही) के बारे में डेटा जनरेट करने के लिए एक REFLECTABLE मैक्रो को परिभाषित करते हैं। इस मैक्रो को इस तरह से बुलाया जाएगा:

 REFLECTABLE ( (const char *) name, (int) age ) 

तो बूस्ट का उपयोग कर। पीपी हम प्रत्येक तर्क पर पुनरावृति करते हैं और इस तरह से डेटा उत्पन्न करते हैं:

 // A helper metafunction for adding const to a type template<class M, class T> struct make_const { typedef T type; }; template<class M, class T> struct make_const<const M, T> { typedef typename boost::add_const<T>::type type; }; #define REFLECTABLE(...) \ static const int fields_n = BOOST_PP_VARIADIC_SIZE(__VA_ARGS__); \ friend struct reflector; \ template<int N, class Self> \ struct field_data {}; \ BOOST_PP_SEQ_FOR_EACH_I(REFLECT_EACH, data, BOOST_PP_VARIADIC_TO_SEQ(__VA_ARGS__)) #define REFLECT_EACH(r, data, i, x) \ PAIR(x); \ template<class Self> \ struct field_data<i, Self> \ { \ Self & self; \ field_data(Self & self) : self(self) {} \ \ typename make_const<Self, TYPEOF(x)>::type & get() \ { \ return self.STRIP(x); \ }\ typename boost::add_const<TYPEOF(x)>::type & get() const \ { \ return self.STRIP(x); \ }\ const char * name() const \ {\ return BOOST_PP_STRINGIZE(STRIP(x)); \ } \ }; \ 

यह क्या करता है एक स्थिर fields_n उत्पन्न करता है जो वर्ग में प्रतिबिंबित करने योग्य फ़ील्ड की संख्या है। फिर यह प्रत्येक फ़ील्ड के लिए field_data को माहिर करता है। यह reflector वर्ग के दोस्त भी हैं, इसलिए यह निजी होने पर भी खेतों तक पहुंच सकता है:

 struct reflector { //Get field_data at index N template<int N, class T> static typename T::template field_data<N, T> get_field_data(T& x) { return typename T::template field_data<N, T>(x); } // Get the number of fields template<class T> struct fields { static const int n = T::fields_n; }; }; 

अब खेतों में फिर से चलना हम आगंतुक पैटर्न का उपयोग करते हैं। हम 0 से फ़ील्ड की संख्या तक एमपीएल रेंज बनाते हैं, और उस इंडेक्स के फ़ील्ड डेटा तक पहुंचते हैं। फिर यह फ़ील्ड डेटा उपयोगकर्ता द्वारा प्रदत्त आगंतुक को देता है:

 struct field_visitor { template<class C, class Visitor, class T> void operator()(C& c, Visitor v, T) { v(reflector::get_field_data<T::value>(c)); } }; template<class C, class Visitor> void visit_each(C & c, Visitor v) { typedef boost::mpl::range_c<int,0,reflector::fields<C>::n> range; boost::mpl::for_each<range>(boost::bind<void>(field_visitor(), boost::ref(c), v, _1)); } 

अब सच्चाई के क्षण के लिए हम सभी को एक साथ जोड़ दिया। यहां पर हम Person वर्ग को कैसे परिभाषित कर सकते हैं:

 struct Person { Person(const char *name, int age) : name(name), age(age) { } private: REFLECTABLE ( (const char *) name, (int) age ) }; 

यहां सामान्यीकृत print_fields फ़ंक्शन है:

 struct print_visitor { template<class FieldData> void operator()(FieldData f) { std::cout << f.name() << "=" << f.get() << std::endl; } }; template<class T> void print_fields(T & x) { visit_each(x, print_visitor()); } 

एक उदाहरण:

 int main() { Person p("Tom", 82); print_fields(p); return 0; } 

कौन से आउटपुट:

 name=Tom age=82 

और वॉयला, हमने सी ++ में प्रतिबिंब को सिर्फ 100 लाइनों के तहत लागू किया है।

मैंने जेएसएएन कोड के लिए मेरे सामान्य संरचना के साथ एक ही समस्या का हल किया है।

मैक्रो को परिभाषित करें: REFLECT (CLASS_NAME, MEMBER_SEQUENCE) जहां MEMBER_SEQUENCE है (नाम) (उम्र) (अन्य) (…)

इस तरह से कुछ का विस्तार करने के लिए संदर्भ लें:

 template<> struct reflector<CLASS_NAME> { template<typename Visitor> void visit( Visitor&& v ) { v( "name" , &CLASS_NAME::name ); v( "age", &CLASS_NAME::age ); ... } } 

आप विज़िटर्स में SEQ का विस्तार करने के लिए BOOST_PP_SEQ_FOREACH का उपयोग कर सकते हैं।

फिर अपने प्रिंट विज़िटर को परिभाषित करें:

 template<typename T> struct print_visitor { print_visitor( T& s ):self(s){} template<typename R> void operator( const char* name, R (T::*member) )const { std::cout<<name<<"= "<<self.*member<<std::endl; } T& self; } template<typename T> void print( const T& val ) { reflector<T>::visit( print_visitor<T>(val) ); } 

http://bytemaster.github.com/mace/group_mace_reflect__typeinfo.html

https://github.com/bytemaster/mace/blob/master/libs/reflect/include/mace/reflect/reflect.hpp

मुझे डर है कि इस कम उपयोग के लिए आपका समाधान बहुत इष्टतम है I जहां हम आपकी सहायता कर सकते हैं, अगर आपके पास print अतिरिक्त अतिरिक्त कार्य हैं जो कि खेतों पर पुनरावृति से लाभान्वित होगा।

यह बूस्ट के लिए एक आदर्श उदाहरण है। फ्यूजन फ्यूजन अनुक्रम ; वे संकलन-समय प्रतिबिंब लागू करने के लिए इस्तेमाल किया जा सकता है उसके ऊपर आप अधिक सामान्य रनटाइम व्यवहार उत्पन्न कर सकते हैं।

इसलिए, आप उदाहरण के लिए फ्यूजन.मैप (जो आपको प्रत्येक प्रकार की एक ही घटना में रोकता है) या अन्य ऐसी कल्पनाओं का उपयोग करके अपने तत्वों को घोषित कर सकते हैं

यदि आपका प्रकार फ्यूजन अनुक्रम के अनुरूप नहीं है (या आप अपने आंतरिक से हस्तक्षेप नहीं करना चाहते हैं), तो अनुकूलन अनुभाग में BOOST_FUSION_ADAPT_STRUCT जैसे कि BOOST_FUSION_ADAPT_STRUCT और निश्चित रूप से, चूंकि हर कोई एक struct (या सार्वजनिक सदस्य नहीं) है, इसलिए कक्षाओं के लिए एक अधिक सामान्य संस्करण भी है, यह जल्द ही जल्द ही बदसूरत हो जाता है: BOOST_FUSION_ADAPT_ADT

त्वरित शुरुआत से चोरी करना :

 struct print_xml { template <typename T> void operator()(T const& x) const { std::cout << '<' << typeid(x).name() << '>' << x << "</" << typeid(x).name() << '>' ; } }; int main() { vector<int, char, std::string> stuff(1, 'x', "howdy"); int i = at_c<0>(stuff); char ch = at_c<1>(stuff); std::string s = at_c<2>(stuff); for_each(stuff, print_xml()); } 

एडेप्टर आपको एक प्रकार "अनुकूलन" करने देंगे, ताकि आप प्राप्त कर सकें:

 struct Foo { int bar; char const* buzz; }; BOOST_FUSION_ADAPT_STRUCT( Foo, (int, bar) (char const*, buzz) ) 

और तब:

 int main() { Foo foo{1, "Hello"); for_each(foo, print_xml()); } 

यह एक बहुत ही प्रभावशाली पुस्तकालय है 🙂

आपको एक ट्यूपल की ज़रूरत है, न कि कक्षा। यह पूर्वप्रक्रमक हैकिंग का सहारा लेने के बिना आसानी से आपकी सभी समस्याओं को हल करेगा

आपको प्रीप्रोसेसर का उपयोग करने की आवश्यकता क्यों है? बढ़ावा देने के लिए परिचय। फ़्यूज़न लाइब्रेरी का कुछ उदाहरण आपके उपयोग-केस के समान है।

पॉल के महान REFLECTABLE मैक्रो के अलावा मेरे 2 सेंट यहां दिए गए हैं मेरे पास क्षेत्र की एक खाली सूची, अर्थात REFLECTABLE() , के लिए एक विरासत पदानुक्रम को ठीक से प्रबंधित करने की आवश्यकता थी निम्न संशोधन इस मामले को संभालता है:

 // http://stackoverflow.com/a/2831966/2725810 #define REFLECTABLE_0(...) \ static const int fields_n = BOOST_PP_VARIADIC_SIZE(__VA_ARGS__); \ friend struct reflector; \ template <int N, class Self> struct field_data {}; \ BOOST_PP_SEQ_FOR_EACH_I(REFLECT_EACH, data, \ BOOST_PP_VARIADIC_TO_SEQ(__VA_ARGS__)) #define REFLECTABLE_1(...) \ static const int fields_n = 0; #define REFLECTABLE_CONST2(b, ...) REFLECTABLE_##b(__VA_ARGS__) #define REFLECTABLE_CONST(b, ...) REFLECTABLE_CONST2(b,__VA_ARGS__) #define REFLECTABLE(...) \ REFLECTABLE_CONST(BOOST_PP_IS_EMPTY(__VA_ARGS__), __VA_ARGS__)