2011-01-25 15 views
9

में प्रकार पंजीकरण मैं निम्नलिखित स्थिति है: लगता है मुझे बेहतर बढ़ावा :: एमपीएल :: वेक्टर की तरह कुछ में प्रकार (functors) जो मैं रजिस्टर/संकलन के दौरान में संकलित करने के लिए चाहते हैं, का एक समूह है। क्या आपको अच्छी तरह से ऐसा करने के लिए कोई चाल पता है?सी ++ संकलन समय चाल

मेरे इच्छा HPP फ़ाइल जो functor प्रकार और पंजीकरण फ़ाइल है, जहां एक मैक्रो संकलन में प्रकार में लाता है लागू करता है।

उदाहरण

// registered.hpp 
REGISTER("functor1.hpp") // implementation 
REGISTER("functor2.hpp") 
... 
boost::mpl::vector<...> types; // full registration vector 

के लिए उम्मीद है कि यह समझ में आता है। धन्यवाद

उत्तर

16

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

संपादित करें: मैं https://github.com/boostcon/2011_presentations/raw/master/thu/Boost.Generic.pdf पर स्लाइड 28 से यह सीखा है।

मैं कोड में एमपीएल का उपयोग नहीं होगा यह आत्म निहित बनाने के लिए।

// The maximum number of types that can be registered with the same tag. 
enum { kMaxRegisteredTypes = 10 }; 

template <int N> 
struct Rank : Rank<N - 1> {}; 

template <> 
struct Rank<0> {}; 

// Poor man's MPL vector. 
template <class... Ts> 
struct TypeList { 
    static const int size = sizeof...(Ts); 
}; 

template <class List, class T> 
struct Append; 

template <class... Ts, class T> 
struct Append<TypeList<Ts...>, T> { 
    typedef TypeList<Ts..., T> type; 
}; 

template <class Tag> 
TypeList<> GetTypes(Tag*, Rank<0>) { return {}; } 

// Evaluates to TypeList of all types previously registered with 
// REGISTER_TYPE macro with the same tag. 
#define GET_REGISTERED_TYPES(Tag) \ 
    decltype(GetTypes(static_cast<Tag*>(nullptr), Rank<kMaxRegisteredTypes>())) 

// Appends Type to GET_REGISTERED_TYPES(Tag). 
#define REGISTER_TYPE(Tag, Type)        \ 
    inline Append<GET_REGISTERED_TYPES(Tag), Type>::type  \ 
    GetTypes(Tag*, Rank<GET_REGISTERED_TYPES(Tag)::size + 1>) { \ 
    return {};            \ 
    }               \ 
    static_assert(true, "") 

प्रयोग उदाहरण:

struct IntegralTypes; 
struct FloatingPointTypes; 

// Initially both type lists are empty. 
static_assert(std::is_same<GET_REGISTERED_TYPES(IntegralTypes), TypeList<>>::value, ""); 
static_assert(std::is_same<GET_REGISTERED_TYPES(FloatingPointTypes), TypeList<>>::value, ""); 

// Add something to both lists. 
REGISTER_TYPE(IntegralTypes, int); 
REGISTER_TYPE(FloatingPointTypes, float); 
static_assert(std::is_same<GET_REGISTERED_TYPES(IntegralTypes), TypeList<int>>::value, ""); 
static_assert(std::is_same<GET_REGISTERED_TYPES(FloatingPointTypes), TypeList<float>>::value, ""); 

// Add more types. 
REGISTER_TYPE(IntegralTypes, long); 
REGISTER_TYPE(FloatingPointTypes, double); 
static_assert(std::is_same<GET_REGISTERED_TYPES(IntegralTypes), TypeList<int, long>>::value, ""); 
static_assert(std::is_same<GET_REGISTERED_TYPES(FloatingPointTypes), TypeList<float, double>>::value, ""); 
+0

क्या आपके पास मेलिंग सूची थ्रेड का लिंक है? – Xeo

+0

दुर्भाग्य से मुझे मूल धागा नहीं मिला जिससे मैंने चाल सीखी। –

0

मैं मैक्रो का उपयोग नहीं होता। सामान्य तकनीक केवल उस वस्तु को परिभाषित करना है जिसका प्रारंभिक पंजीकरण पंजीकरण करता है। Pitfall: आपको कुछ संदर्भ करने की जरूरत है, उदा। , एक समारोह फोन क्रम में संकलन इकाई में उस में लिंक कर लिया है करने के लिए।

चीयर्स & hth।,

+0

आदर्श रूप में मैं एक लाइन के साथ कंटेनर में उन सभी प्रकार शामिल करना चाहते हैं। मुझे पता है कि मैं इसे अन्यथा 2-3 लाइनों के साथ कर सकता हूं, लेकिन मैं जानना चाहता हूं कि कोई चाल है या नहीं। – Anycorn

-3

आप एमपीएल :: वेक्टर विचार का समाधान नहीं करेंगे। आप टेम्पलेट "चर" को बदल नहीं सकते हैं। याद रखें कि टेम्पलेट मेटाप्रोग्रामिंग एक शुद्ध कार्यात्मक भाषा है। बिल्कुल कोई दुष्प्रभाव नहीं।

पंजीकरण के लिए ... मैक्रो चीज ठीक काम करती है। मैक्रो को परिभाषित करें ताकि यह पंजीकरण प्रक्रिया के साथ कुछ छोटे ग्लोबल वैरिएबल को घोषित और आरंभ कर सके। वैकल्पिक रूप से आप सड़क मैं यहाँ किया नीचे जाना कर सकते हैं:

How to force inclusion of "unused" object definitions in a library

नोट ठीक है अगर आप एक पुस्तकालय में यह करने के लिए कोशिश कर रहे हैं।

+0

मेरा विचार इस तरह था: पहला पंजीकरण -> प्रकार 1, टाइप 2, आदि बनाने के लिए दूसरा संलग्न करें ... Finaly typedef typeN प्रकारों के लिए। – Anycorn

+1

'mpl :: for_each' आपको रन टाइम पर दुष्प्रभाव देता है। संभवतः आप एक प्रकार के 'mpl :: vector' प्रकार का निर्माण कर सकते हैं जो आप कुछ भी कर सकते हैं; शायद कुछ प्रकार की पॉलिसी श्रृंखला? वैसे भी, 'for_each' और' fold' परिवार दोनों आपको संरचनाएं बनाने की अनुमति देते हैं जिनमें रनटाइम प्रभाव हो सकते हैं। मेरा पसंदीदा एक कॉन्स कार/सीडीआर प्रकार टेम्पलेट है जो एक एमपीएल :: contraint के खिलाफ परीक्षण करता है और या तो कार के सदस्य को कॉल करता है या विस्तार करता है और सीडीआर की कार को कॉल करता है। – KitsuneYMG

+0

@ymg - हां, लेकिन एकाधिक, स्वतंत्र स्थानों से एमपीएल अनुक्रम बनाने का कोई तरीका नहीं है। एकमात्र चीज जो आप संभवतः कर सकते हैं वह कहीं एक अनुक्रम परिभाषित करता है और इसका उपयोग करता है। तो वहां कोई "पंजीकरण" विषय नहीं होगा। यह फैक्ट्री को उप-वर्गीकृत करने और इसके कन्स्ट्रक्टर में प्रकारों को हार्ड-कोडिंग करने से कहीं अधिक कुशल नहीं होगा। वास्तव में कम वास्तव में। –

संबंधित मुद्दे