2015-10-27 15 views
8

पर आधारित उचित प्रति-कन्स्ट्रक्टर का चयन करना मैं टेम्पलेट तर्क मान के आधार पर किसी सदस्य फ़ंक्शन (कॉपी कन्स्ट्रक्टर) के कार्यान्वयन का चयन करना चाहता हूं। मुझे लगता है कि दो दृष्टिकोण हैं: SFINAE और टेम्पलेट आंशिक विशेषज्ञता।टेम्पलेट पैरामीटर

पिछले एक माना जाता है कि इस तरह दिखता है:

#include <iostream> 

template<typename A, bool sw> 
struct B 
{ 
    B() {} 
    B(const B &b); 
}; 

template<typename A> 
B<A, false>::B(const B<A, false> &b) 
{ 
    std::cout << "false\n"; 
} 

template<typename A> 
B<A, true>::B(const B<A, true> &b) 
{ 
    std::cout << "true\n"; 
} 

int main() 
{ 
} 

यह संकलन नहीं करता है: nested name specifier 'B<A, false>::' for declaration does not refer into a class, class template or class template partial specialization

SFINAE दृष्टिकोण भी विफल रहता है:

#include <type_traits> 
#include <iostream> 

template<typename A, bool sw> 
struct B 
{ 
    B() {} 

    template<typename U = typename std::enable_if<sw, B>::type> 
    B(const U &b) 
    { 
     std::cout << "true\n"; 
    } 

    template<typename U = typename std::enable_if<!sw, B>::type> 
    B(const U &b) 
    { 
     std::cout << "false\n"; 
    } 
}; 

int main() 
{ 
    { 
     B<int, true> b; 
     auto bc = b; // cout << true 
    } 
    { 
     B<int, false> b; 
     auto bc = b; // cout << false 
    } 
} 

संकलन त्रुटि यहाँ constructor cannot be redeclared और no type named 'type' in 'std::enable_if<false, B<int, false> >'; 'enable_if' cannot be used to disable this declaration है।

क्या समस्याएं ठीक करने या अन्यथा टेम्पलेट पैरामीटर के आधार पर उपयुक्त प्रति-निर्माता का चयन करने का कोई तरीका है?

+1

आप आंशिक विशेषज्ञता एक वर्ग (या संरचना) का सिर्फ सदस्यों पर नहीं कर सकते , आपको आंशिक रूप से पूर्ण वर्ग का विशेषज्ञ होना चाहिए। रिकॉर्ड के लिए –

+1

, यहां की समस्याओं में से एक यह है कि आपके पास एक टेम्पलेट कॉपी-कन्स्ट्रक्टर नहीं हो सकता है (इस तथ्य को छोड़कर कि आपके हस्ताक्षर में दो हस्ताक्षर समान हैं, इसे ठीक किया जा सकता है), क्योंकि एक पूर्ण रूप से जेनरेट की गई प्रति- कन्स्ट्रक्टर हमेशा अधिभार संकल्प में जीतता है –

उत्तर

4
template <typename A, bool sw> 
struct B 
{ 
    B() = default; 

    B(const B& b) : B(b, std::integral_constant<bool, sw>{}) {} 

private: 
    B(const B& b, std::true_type) 
    { 
     std::cout << "true\n"; 
    } 

    B(const B& b, std::false_type) 
    { 
     std::cout << "false\n"; 
    } 
}; 

DEMO

0

मैं जानता हूँ कि यह एक न्यूनतम उदाहरण है, लेकिन क्या

B(const B& b) { 
    if(sw) { 
    std::cout << "true\n"; 
    } else { 
    std::cout << "false\n"; 
    } 
} 
+0

हां, यह समस्या हल करता है। लेकिन मेरे मामले में कॉपी कन्स्ट्रक्टर का उपयोग करता है या नहीं ('sw' पर निर्भर करता है) कन्स्ट्रक्टर प्रतिनिधिमंडल। –

1

@Joachim Pileborg के रूप में टिप्पणी में कहा साथ कुछ गड़बड़ है, तो आप एक वर्ग का सिर्फ एक सदस्य विशेषज्ञ नहीं कर सकते , आपको पूरी कक्षा का विशेषज्ञ होना है। तो अपने आंशिक विशेषज्ञता इस तरह दिखेगा:

template<typename A, bool sw> 
struct B 
{ 
    B() {} 
    B(const B &b); 
}; 

//Specialize when sw is false 
template<typename A> 
struct B<A, false> 
{ 
    //The constructor in the specialized struct print false 
    B(const B &b) 
    { 
     std::cout << "false\n"; 
    } 
}; 

//Specialize when sw is true 
template<typename A> 
struct B<A, true> 
{ 
    //The constructor in the specialized struct print true 
    B(const B &b) 
    { 
     std::cout << "true\n"; 
    } 
}; 

सबसे अच्छा समाधान आप SFINAE के लिए प्राप्त कर सकते हैं @Piotr Skotnicki द्वारा दिया गया था

+0

* "क्योंकि आप एक कन्स्ट्रक्टर को पुन: प्राप्त नहीं कर सकते हैं" * आप जितनी बार चाहें उतनी बार पुन: प्राप्त कर सकते हैं (हस्ताक्षर बदलकर, 'टाइपनाम = शून्य' जैसे डमी टेम्पलेट पैरामीटर को जोड़ने की तरह, यहां समस्या यह है कि, भले ही यह हो निश्चित, एक स्पष्ट रूप से जेनरेट की गई प्रति-कन्स्ट्रक्टर को हमेशा बेहतर उम्मीदवार के रूप में चुना जाएगा (क्योंकि यह एक गैर-टेम्पलेट है) –

+0

आप सही हैं और मुझे अपने जवाब में यह कहना चाहिए था कि आप एक ही हस्ताक्षर के साथ एक कन्स्ट्रक्टर को फिर से नहीं ले सकते हैं। – Pumkko

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