2012-08-29 19 views
6

के टेम्पलेट परिवार से प्राप्त किया गया है या नहीं, यह जांचने के लिए कि कक्षा बी को std :: vector से प्राप्त किया गया है या नहीं?कक्षा बी को कक्षा

template<class A> 
struct is_derived_from_vector { 
    static const bool value = ????; 
}; 

कक्षा बी टेम्पलेट परिवार से प्राप्त किया गया है या नहीं, संकलित समय पर परीक्षण कैसे करें?

template<class A, template<class> class Family> 
struct is_derived_from_template { 
    static const bool value = ????; 
}; 

का उपयोग करना:

template<class T> struct X {}; 

struct A : X<int> {} 
struct B : std::vector<char> {} 
struct D : X<D> {} 

int main() { 
    std::cout << is_derived_from_template<A, X>::value << std::endl; // true 
    std::cout << is_derived_from_template<D, X>::value << std::endl; // true 
    std::cout << is_derived_from_vector<A>::value << std::endl; // false 
    std::cout << is_derived_from_vector<B>::value << std::endl; // true 
} 
+4

, यह स्पष्ट करने के लिए है कि क्या आप केवल एक सी ++ 03 या एक सी ++ 11 समाधान अच्छा है की जरूरत है महत्वपूर्ण है (हालांकि मैं कर रहा हूँ नहीं लगता है कि सी ++ 11 यहाँ मदद कर सकते हैं) । और एक स्मार्ट टिप्पणी के रूप में, यह देखते हुए कि आपको कभी भी मानक कंटेनरों से उत्तराधिकारी नहीं होना चाहिए, मूल विशेषता सरल है: 'झूठी': पी –

+0

सी ++ 03। मैं msvc 2010 कंपाइलर का उपयोग करता हूं। इसलिए मैं इसके अलावा 'decltype' का उपयोग करने के लिए सहमत हूं। 'std :: vector' उदाहरण के लिए है। यदि आप सी ++ 03 समाधान नहीं जानते हैं तो सी ++ 11 समाधान भी आपका स्वागत है। –

उत्तर

12

इस प्रयास करें:

#include <type_traits> 

template <typename T, template <typename> class Tmpl> // #1 see note 
struct is_derived 
{ 
    typedef char yes[1]; 
    typedef char no[2]; 

    static no & test(...); 

    template <typename U> 
    static yes & test(Tmpl<U> const &); 

    static bool const value = sizeof(test(std::declval<T>())) == sizeof(yes); 
}; 

उपयोग:

#include <iostream> 

template<class T> struct X {}; 

struct A : X<int> {}; 

int main() 
{ 
    std::cout << is_derived<A, X>::value << std::endl; 
    std::cout << is_derived<int, X>::value << std::endl; 
} 

नोट: लाइन में चिह्नित #1, आप कर सकते थे यह भी सुनिश्चित अपनी विशेषता writint द्वारा स्वीकार कम से कम एक है कि किसी भी टेम्पलेट, लेकिन संभवतः अधिक प्रकार तर्क:

template <typename, typename...> class Tmpl 
+0

यदि आप 'टेम्पलेट कक्षा Tmpl' का उपयोग करते हैं और अपने परीक्षण फ़ंक्शन के लिए पैरामीटर पैक का उपयोग करते हैं, तो आपको किसी भी प्रकार के तर्कों के साथ टेम्पलेट को संभालने में सक्षम होना चाहिए, केवल एक ही नहीं। –

+1

इस दृष्टिकोण के साथ समस्या यह है कि यह केवल एक तर्क के साथ टेम्पलेट्स के लिए काम करेगा। यहां तक ​​कि यदि आप 'std :: vector' के सामान्य * दो तर्क लेने के लिए इसे बढ़ाते हैं, तो कार्यान्वयन को अतिरिक्त टेम्पलेट पैरामीटर जोड़ने की अनुमति है (जब तक यह उन पैरामीटर के लिए डिफ़ॉल्ट मान प्रदान करता है), इसलिए यह 100% पोर्टेबल नहीं होगा –

+1

@ डेविडरोड्रिगुएज़-ड्राईबीस: हाँ, इसे विविध बनाओ ... –

1

मैं एक ही स्थिति है कि मैं एक वर्ग एक वेक्टर से प्राप्त होता है, तो पता करने के लिए (जैसे की जरूरत थी)-कक्षा। दुर्भाग्य से मेरे प्रोजेक्ट में कोई सी ++ - 11 या वैरिएड मैक्रोज़ नहीं है। तो मेरी समाधान Kerrek's answer का एक मिश्रण और अंत में कुछ googletest-कोड के साथ इस article था:

#include <vector> 

template <typename T> 
class is_derived_from_vector 
{ 
    typedef char Yes_t[1]; 
    typedef char No_t[2]; 

    static No_t& test(const void* const); 

    template <typename U> 
    static Yes_t& test(const std::vector<U>* const); 

public: 
    static const bool value = ((sizeof(test(static_cast<T*>(0)))) == (sizeof(Yes_t))); 
}; 

template<class T> struct X {}; 
struct A : X<int> {}; 
struct B : std::vector<char> {}; 

TEST(Example, IsDerivedFrom) 
{ 
    EXPECT_FALSE(is_derived_from_vector<A>::value); 
    EXPECT_TRUE(is_derived_from_vector<B>::value); 
} 

किसी खाके के लिए एक आम समाधान मुझे लगता है कि नहीं सी ++ के उपयोग के बिना परिभाषित करने के लिए संभव हो जाएगा - 11 या उसके बाद।

0

मैं लंबे समय तक नहीं पहले इस समस्या के समाधान के लिए देख रहा था और

आधुनिक सी ++ डिजाइन के साथ परामर्श के बाद: जेनेरिक प्रोग्रामिंग और डिजाइन पैटर्न लागू

मैं निम्नलिखित का निर्माण करने में सक्षम था जो टिप्पणियों में प्रदान की गई चीज़ों के समान ही कम है।

#include <iostream> 
#include <type_traits> 
#include <utility> 

template <typename T, template <typename...> class U> 
struct is_derived 
{ 
private: 
    template <typename...Ts> 
    static constexpr std::true_type check(const U<Ts...>&); 
    static constexpr std::false_type check(...); 


    template <typename> 
    struct is_same 
    { 
     static constexpr bool value = false; 
    }; 

    template <typename...Ts> 
    struct is_same <U<Ts...>> 
    { 
     static constexpr bool value = true; 
    }; 

    public: 
    static constexpr bool value = 
     std::is_same<decltype(check(std::declval<T>())), 
        std::true_type>::value && 
     !is_same<T>::value; 
}; 

template <typename, typename> 
struct X 
{ 
}; 

template <typename T> 
struct Y : X <T, int> 
{ 
}; 


int main(int argc, char **argv) { 

    std::cout << std::boolalpha << is_derived<Y<int>, X>::value << std::endl; 
    std::cout << std::boolalpha << is_derived<X<int,int>, X>::value << std::endl; 
    std::cout << std::boolalpha << is_derived<int, X>::value << std::endl; 

    return 0; 
} 
टेम्पलेट metaprogramming साथ