2012-03-10 8 views
6

मेरी प्रोजेक्ट में, मैं कुछ मौजूदा बड़ी कक्षाओं के टेम्पलेट प्रॉक्सी क्लास को कार्यान्वित करना चाहता हूं। मौजूदा वर्ग लाइब्रेरी कक्षाएं हैं, इसलिए उन्हें संशोधित नहीं किया जा सकता है। ज्यादातर मामलों में, ग्राहकों को पता नहीं है कि वस्तुओं प्रॉक्सी वर्ग या बड़ी कक्षा के उदाहरण हैं। कुछ मामलों में, हालांकि, ग्राहकों को विस्तृत कक्षा की जानकारी जाननी चाहिए। चूंकि प्रॉक्सी क्लास स्वयं टेम्पलेट क्लास है, इसलिए मुझे नहीं लगता कि क्लास नाम से सरल फ़ंक्शन ओवरलोडिंग इस समस्या को हल कर सकती है। संभावित समाधान मैंने सोचा कि प्रॉक्सी क्लास के अंदर एक आंतरिक नेस्टेड क्लास या टाइपपीफ जोड़ना है, और क्लाइंट यह जांचता है कि क्लास की जानकारी प्राप्त करने के लिए यह क्लास/टाइपपीफ मौजूद है या नहीं। मेरा सवाल है: कैसे जांचें कि किसी वर्ग ने नेस्टेड क्लास परिभाषा या सी ++ 11 में टाइपपीफ निर्दिष्ट किया है या नहीं?कैसे जांचें कि किसी वर्ग ने नेस्टेड क्लास परिभाषा या सी ++ 11 में टाइपपीफ निर्दिष्ट किया है या नहीं?

#include <iostream> 
#include <functional> 
#include <string> 
#include <vector> 
#include <type_traits> 

typedef std::string CBig1; // use string for demonstration 
typedef std::string CBig2; // use string for demonstration 

//class CBig1; // the bigger class 1, codes of which can not be changed 
//class CBig2; // the bigger class 2, codes of which can not be changed 

template <typename _Big, typename _Other> 
class CProxy 
{ 
public: 
    struct proxy_tag { }; 
}; 

// how to implement this ? 
// the proxy traits class, if defined _T::proxy_tag, the ``type'' will be std::true_type, otherwise the ``type'' will be std::false_type 
template <typename _T> 
struct is_proxy 
{ 
    //typedef std::true_type type; 
    //typedef std::false_type type; 
}; 

template <typename _T> 
void ClientHelp(const _T& t, std::false_type) 
{ 
    // process real class 
    std::cerr << "real class" << std::endl; 
} 

template <typename _T> 
void ClientHelp(const _T& t, std::true_type) 
{ 
    // process proxy class 
    std::cerr << "proxy class" << std::endl; 
} 

template <typename _T> 
void Client(const _T& t) 
{ 
    ClientHelp(t, typename is_proxy<_T>::type()); 
} 

int main(int argc, char* argv[]) 
{ 
    CBig1 b; 
    CProxy<CBig1, int> p; 
    Client(b); 
    Client(p); 
    return 0; 
} 

कैसे लक्षण वर्ग is_proxy लागू करने के लिए:

निम्नलिखित कोड का एक उदाहरण दिखाते हैं?

+0

[SFINAE] का उपयोग करें (http://en.wikipedia.org/wiki/SFINAE)। – iammilind

+3

'_This' जैसे नामों का उपयोग न करें, वे कार्यान्वयन के लिए आरक्षित हैं। – Xeo

उत्तर

10

सी ++ 11 में सी ++ 03 संस्करण के लिए एक पूरक, आप decltype मिल के रूप में:

template <typename T> 
auto is_proxy(T const&) -> decltype(T::proxy_tag{}, std::true_type{}) { 
    return std::true_type{}; 
} 

std::false_type is_proxy(...) { return std::false_type{}; } 

और Client अपने क्रियान्वयन हो जाता है:

template <typename T> 
void Client(T const& t) { 
    ClientHelp(t, is_proxy(t)); 
} 

मीठा, नहीं है यह

+0

यह मेरे लिए संकलित नहीं है (एसवीएन से काफी हालिया क्लैंग ++)। समस्या 'decltype()' के लिए ** ** ** ** तर्क लगता है। यह कैसे काम करना चाहिए? –

+3

@MichaelWild: यह अनुक्रम ऑपरेटर ',' का उपयोग करता है। आप आम तौर पर इसे लूप स्थितियों में पाते हैं, जैसे 'for (;;++ i, ++ e) ', अनुक्रम ऑपरेटर दोनों ऑपरेटरों को बाएं से दाएं से मूल्यांकन करता है और सही ऑपरेंड का परिणाम देता है। इसे भी जंजीर किया जा सकता है: '++ ए, ++ बी, ++ सी'' ++ सी' के परिणाम को वापस कर देगा, और आपको गारंटी है कि मूल्यांकन का क्रम '++ ए' * फिर *' + है + बी' * फिर * '++ सी'। यहां केवल एकमात्र उपयोग एसएफआईएनएई चेक के बाईं ओर और दाईं ओर वांछित वापसी प्रकार उत्पन्न करने वाली अभिव्यक्ति पर है। आप पूरी चीज कोष्ठक की दूसरी परत में लपेटने का प्रयास कर सकते हैं। –

+0

मुझे बहुत संदेह था (मुझे यकीन नहीं था कि संकलक यहां पार्स कैसे कर रहा था)। शायद मुझे अतिरिक्त कोष्ठक जोड़ने की ज़रूरत है? लेकिन फिर AFAIK, 'decltype' बहुत ही अनोखा है जब यह कोष्ठक की बात आती है ... –

16

आप एक वर्ग एक प्रॉक्सी बनाने के लिए हल्के प्रकार वर्गीकरण मुहावरा

template<class T, class R = void> 
struct enable_if_type { typedef R type; }; 

template<class T, class Enable = void> 
struct test : std::false_type {}; 

template<class T> 
struct test<T, typename enable_if_type<typename T::is_proxy_tag>::type> : std::true_type 
{}; 

template <typename _Big, typename _Other> 
class CProxy 
{ 
    public: 
    typedef void is_proxy_tag; 
}; 

तो उपयोग कर सकते हैं तो बस इस

typedef void is_proxy_tag; 

और enable_if_type में SFINAE जोड़ने उचित true_type/false_type विशेषज्ञता का चयन करेंगे

ध्यान दें किके बजाय boost::mpl::true_ का उपयोग करनाआदि इस समाधान को सी ++ 03 के लिए काम करता है।

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

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