2013-05-24 17 views
5

मैं एक टेम्पलेटेड संरचना के अंदर कुछ SFINAE का उपयोग करने की कोशिश कर रहा हूं। मैं निम्नलिखित करने के लिए मेरी समस्या कम है और यह काम कर सकता है: इस कोड के साथअपूर्ण प्रकार का अमान्य उपयोग (SFINAE)

template<bool mybool> 
struct test { 
    void myfunc(); 
}; 

template<bool mybool> 
void test<mybool>::myfunc() { 
    std::cout << "test true" << std::endl; 
} 
template<> 
void test<false>::myfunc() { 
    std::cout << "test false" << std::endl; 
} 

int main(int argc, char ** argv) { 
    test<true> foo; 
    test<false> bar; 
    foo.myfunc(); 
    bar.myfunc(); 
} 

, मैं परिणाम प्राप्त:

test true 
test false 

हालांकि, अगर मैं एक से अधिक के साथ कि मेरी struct test पर विचार करना चाहते टेम्पलेट पैरामीटर, मैं इस तरह से ऊपर अनुकूल की कोशिश की:

template<int myint, bool mybool> 
struct test { 
    void myfunc(); 
}; 

template<int myint, bool mybool> 
void test<myint,mybool>::myfunc() { 
    std::cout << "test true" << std::endl; 
} 
template<int myint> 
void test<myint,false>::myfunc() { 
//error: invalid use of incomplete type 'struct test<myint, false>' 
    std::cout << "test false" << std::endl; 
} 

int main(int argc, char ** argv) { 
    test<1,true> foo; 
    test<1,false> bar; 
    foo.myfunc(); 
    bar.myfunc(); 
} 

मैं अधूरा प्रकार 'struct परीक्षण' का गलत उपयोग हो रही है।

क्या मैं गलत दिशा में जा रहा हूं? क्या मैं ऐसा करना चाहता हूं जो मैं करना चाहता हूं? आपकी मदद के लिए धन्यवाद!

+0

आपका मतलब है 'foo.myfunc (मैं उसका जवाब टिप्पणी नहीं कर सकता, इसलिए मैं अपने खुद के पोस्ट)()' जब आप 'लिखा foo.test()'? – bitmask

+0

आपने दूसरे उदाहरण में 'myfunc' गलत भी लिखा है। यह 'my_func' होना चाहिए। कृपया उन्हें पोस्ट करने से पहले अपने उदाहरणों को आजमाएं। – pmr

उत्तर

6

आप आंशिक रूप से सदस्य फ़ंक्शन का विशेषज्ञ नहीं हो सकते हैं, आपको partially specialize पूर्ण संरचना चाहिए। आप अपने वर्ग है, जो आप के बाद से (सदस्य) कार्यों का आंशिक विशेषज्ञता की अनुमति नहीं है, तो आप अपने प्रकार विघटित कर सकता करने के लिए होता है फिर से परिभाषित करने से बचना चाहते हैं निम्न उदाहरण सही ढंग से

template<int myint, bool mybool> 
struct test { 
    void my_func(); 
}; 

template<int myint, bool mybool> 
void test<myint,mybool>::my_func() { 
    std::cout << "test true" << std::endl; 
} 

template<int myint> 
struct test<myint, false> { 
    void my_func(); 
}; 

template<int myint> 
void test<myint,false>::my_func() { 
//error: invalid use of incomplete type 'struct test<myint, false>' 
    std::cout << "test false" << std::endl; 
} 

int main(int argc, char ** argv) { 
    test<1,true> foo; 
    test<1,false> bar; 
    foo.my_func(); 
    bar.my_func(); 
} 
+0

ठीक है, आपके समाधान की कोशिश की और यह काम indeeed। हालांकि, मान लें कि मेरे पास मेरी कक्षा में बहुत सारी विशेषता है, मैं वास्तव में उन्हें दोनों संरचनाओं में घोषित नहीं करना चाहता हूं। लेकिन अगर मैं उन्हें केवल पहले ही घोषित करता हूं, तो मैं उन्हें विशेष से एक्सेस नहीं कर पाऊंगा। क्या मेरे लिए सब कुछ की घोषणा को दोगुना करने का कोई तरीका नहीं है? – Kiplaki

+1

@ किप्लाकी हां, कुछ आधार/लक्षण प्रकार का उपयोग करें। – ForEveR

+0

@ किप्लाकी या 'false_type/true_type' के साथ अधिभार पर प्रेषण। – pmr

3

काम करेंगे।

template<int myint, bool mybool> 
struct test { 
    char some_var; 
    std::vector<int> more_var; 
    void my_func(); 
}; 

को बदलें:: इस कोड की पुनरावृत्ति को कम कर देंगे

template<int myint> 
struct test_static { 
    protected: 
    char some_var; 
    std::vector<int> more_var; 
}; 

template <int myint, bool mybool> 
struct test : private test_static<myint> { 
    void my_func() { 
     // default case 
    } 
}; 
template <int myint> 
struct test<myint,false> : private test_static<myint> { 
    void my_func() { 
     // special case 
    } 
}; 
बेशक

, अगर आप बाहर करने के लिए सभी सदस्यों की पूर्ण दृश्यता चाहते हैं, उन्हें पहली जगह में protected नहीं बनाते हैं और private विरासत के बजाय public का उपयोग करें।

3

मेरी स्मृति को रीफ्रेश करने के लिए SFINAE सिद्धांत पर पहले this question पर देखकर, मैंने परिणाम प्राप्त करने का प्रयास किया जिसे आप कोड में न्यूनतम अनावश्यकता के साथ ढूंढ रहे हैं।

मैं भी इस विषय पर wikipedia लेख है, जो मुझे संकेत दिया जाँच की है कि आप एक कार्यक्षमता समान की जरूरत भी boost::enable_if सशर्त अपने कार्य inmplementation चयन करने के लिए:

// simplified version of boost::enable_if_c and disable_if_c to match your exact need 

template <bool B> 
struct enable_if_c { 
    typedef void type; 
}; 

struct enable_if_c<false>{}; 

template <bool B> 
struct disable_if_c { 
    typename void type; 
}; 

struct disable_if_c<true> {}; 

template<bool mybool, typename T> 
struct test { 
    template <bool d> 
    typename enable_if_c<d>::type my_func_impl(){ 
     cout << "true" << endl; 
    } 
    template <bool d> 
    typename disable_if_c<d>::type my_func_impl(){ 
     cout << "false" << endl; 
    } 
    void my_func(){ my_func_impl<mybool>(); } 
}; 

आप के साथ struct बाहर my_func_impl निकायों परिभाषित कर सकते हैं निम्न सिंटैक्स:

template <bool mybool, typename T> 
template <bool d> 
typename enable_if_c<d>::type test<mybool,T>::my_func_impl(){ 
    cout << "true" << endl; 
} 

समस्या की मुश्किल बात यह है कि आप एक सरल ओवरलोडिंग पर भरोसा नहीं कर सकते हैं, क्योंकि आप चाहते हैं रों है एएम फ़ंक्शन प्रोटोटाइप, इसलिए विशेष रूप से एक या अन्य कार्यान्वयन को परिभाषित करने की आवश्यकता है।

0

आप diderc द्वारा प्रदान की जवाब देने के लिए एक छोटे से सुधार जोड़ सकते हैं, बस एक छोटे संशोधन है कि आप जो अपने कार्यों के नाम अपवित्र हैं एक सहायक समारोह के उपयोग से बचने के लिए सक्षम बनाता द्वारा:

बजाय:

template <bool d> 
typename enable_if_c<d>::type my_func_impl(){ 
    cout << "true" << endl; 
} 
template <bool d> 
typename disable_if_c<d>::type my_func_impl(){ 
    cout << "false" << endl; 
} 
void my_func(){ my_func_impl<mybool>(); } 

बस लिखें:

template <bool d = mybool> 
typename enable_if_c<d>::type my_func(){ 
    cout << "true" << endl; 
} 
template <bool d = mybool> 
typename disable_if_c<d>::type my_func(){ 
    cout << "false" << endl; 
} 

और यदि आप सी ++ 11 का उपयोग कर सकते हैं, तो आप enable_if_c और disabled_if_c को std::enable_if द्वारा प्रतिस्थापित कर सकते हैं।

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