2011-09-30 5 views
6

मुझे एक समस्या है जहां मैं एक फ़ंक्शन foo का एक सामान्य संस्करण प्रदान करना चाहता हूं जो केवल तब लागू हो सकता है जब किसी आमंत्रण के लिए बिल्कुल कोई अन्य मिलान न हो। मैं निम्नलिखित कोड को कैसे संशोधित कर सकता हूं जैसे last_resort::fooderived::typebase::foo से अधिक खराब मिलान है? मैं एक समाधान खोजना चाहता हूं जिसमें bar की परिभाषा को संशोधित करने में शामिल नहीं है और जो last_resort::foo के तर्क के प्रकार को संरक्षित रखेगा।एडीएल के दौरान फ़ंक्शन टेम्पलेट को कम से कम प्राथमिकता कैसे बनाएं?

#include <iostream> 

namespace last_resort 
{ 

template<typename T> void foo(T) 
{ 
    std::cout << "last_resort::foo" << std::endl; 
} 

} 

template<typename T> void bar(T) 
{ 
    using last_resort::foo; 
    foo(T()); 
} 

namespace unrelated 
{ 

struct type {}; 

} 

namespace base 
{ 

struct type {}; 

void foo(type) 
{ 
    std::cout << "base::foo" << std::endl; 
} 

} 

namespace derived 
{ 

struct type : base::type {}; 

} 

int main() 
{ 
    bar(unrelated::type()); // calls last_resort::foo 
    bar(base::type());  // calls base::foo 
    bar(derived::type()); // should call base::foo, but calls last_resort::foo instead 

    return 0; 
} 

उत्तर

0

last_resort::foo अधिभार disable_if के साथ सेट से हटाया जा सकता। विचार last_resort::foo(T) को अक्षम करना है यदि foo(T) अन्यथा अच्छी तरह से गठित किया गया है।

namespace test 
{ 

template<typename T> struct has_foo { ... }; 

} 

namespace last_resort 
{ 

template<typename T> 
    struct disable_if_has_foo 
    : std::enable_if< 
     !test::has_foo<T>::value 
     > 
{}; 

template<typename T> 
    typename disable_if_has_foo<T>::type foo(T) 
{ 
    std::cout << "last_resort::foo" << std::endl; 
} 

} 

उत्पादन:

$ g++ last_resort.cpp 
$ ./a.out 
last_resort::foo 
base::foo 
base::foo 

This answer बताता है कि कैसे एक समारोह (foo) void लौटने के अस्तित्व के लिए जाँच के लिए एक समाधान का निर्माण करने यह last_resort::foo(T)foo के लिए सबसे खराब मैच होने के लिए कारण बनता है।

1

आप इसके बारे में ज्यादा कुछ नहीं कर सकते हैं। दोनों foo फ़ंक्शन ओवरलोड सेट में हैं। लेकिन आपका last_resort एक बेहतर मिलान है क्योंकि इसे व्युत्पन्न :: प्रकार() के लिए आधार :: foo के विपरीत रूपांतरण की आवश्यकता नहीं है। केवल उस मामले में जहां दो उम्मीदवार पैरामीटर और संभावित रूपांतरणों के आधार पर "समान रूप से अच्छे" हैं, एक गैर-टेम्पलेट को प्राथमिकता दी जाती है।

+0

यह सच है, लेकिन मुझे आश्चर्य है कि क्या डिफ़ॉल्ट मूल्यों के साथ कुछ अतिरिक्त पैरामीटर के साथ इसे बढ़ाकर foo में "छुपा" रूपांतरण शुरू करने का कोई तरीका है? –

+0

मुझे नहीं लगता कि यह काम करेगा। जो मैं कह सकता हूं उससे "सर्वश्रेष्ठ" आप एक अस्पष्टता प्राप्त कर सकते हैं ताकि संकलन विफल हो जाए। लेकिन शायद, मैं कुछ भी याद कर रहा हूँ। – sellibitze

+0

यह समाधान '' 'last_resort :: foo''' के रिटर्न प्रकार को' '' disabled_if_foo_exists :: टाइप''' के साथ सजाने के लिए प्रतीत होता है, जो एक मुफ्त '' 'foo की जांच करने के लिए SFINAE का उपयोग करेगा '' 'समारोह यदि कोई मौजूद है, तो '' 'last_resort :: foo''' ओवरलोड सेट से हटा दिया जाएगा। –

0

derived::type की घोषणा के बाद आप derived::type टाइप करने के लिए bar का अधिभार प्रदान कर सकते हैं। यह namespace derived में हो सकता है या नहीं।

void bar(derived::type) 
{ 
    foo(derived::type()); 
} 
2

इस बारे में के रूप में बुरा के रूप में यह हो जाता है होगा:

struct badParam { template <typename T> badParam(T t) { } }; 
namespace last_resort { 
    void foo(badParam, int dummy = 0, ...) { 
    std::cout << "last_resort::foo" << std::endl; 
    } 
} 

आप एक उपयोगकर्ता-निर्धारित रूपांतरण, एक डिफॉल्ट पैरामीटर और एक अप्रयुक्त अंडाकार मिल गया है।

[संपादित करें]

थोड़ा सा संस्करण है, T को बचाने के लिए मैं डमी पैरामीटर के लिए उपयोगकर्ता परिभाषित रूपांतरण ले जाया गया:

struct badParam { 
    badParam() { } 
    operator int() { return 42; } 
}; 
namespace last_resort { 
    template <typename T> void foo(T t, int dummy = badParam(), ...) { 
    std::cout << "last_resort::foo" << std::endl; 
    } 
} 
+0

धन्यवाद। मुझे लगता है कि केवल '' 'BadParam' को जोड़ना पर्याप्त रूप से इसे हटाने के लिए पर्याप्त है, लेकिन यह रूपांतरण में '' '' '' '' प्रकार के प्रकार को मिटा देता है। –

+0

ठीक है, अंतिम उपाय मामले के लिए, आप आमतौर पर टी पर भरोसा नहीं कर सकते हैं, क्योंकि आपको सभी अजीब प्रकार मिलते हैं। लेकिन इसे बचाने में मुश्किल है। टेम्पलेट तर्क कटौती उन उपयोगकर्ता परिभाषित रूपांतरणों का उत्पादन नहीं करती है। – MSalters

+0

प्राचीन पोस्ट, लेकिन यादृच्छिक विचार: मूल 'BadParam' का उपयोग करने के बारे में, लेकिन' BadParam 'को टेम्पलेट तर्क मान सूचक के साथ टेम्पलेट तर्क मान सूचक के साथ एक टेम्पलेट प्रकार बनाने के लिए, जो इसके कन्स्ट्रक्टर में ऐसा करता है। – Yakk

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