2013-03-28 13 views
6

के साथ फ़ंक्शन ओवरलोडिंग मैं अधिभारित फ़ंक्शन बनाना चाहता हूं जो बेस क्लास और व्युत्पन्न कक्षाओं में साझा पॉइंटर लेते हैं। ऐसा लगता है कि संदर्भ और कच्चे पॉइंटर्स के लिए काम करना है, लेकिन अतिरिक्त व्युत्पन्न वर्ग के मामले में साझा पॉइंटर्स के लिए नहीं। जब Visual Studio 2012 का उपयोग कर, लेकिन जब मैं यहाँ http://ideone.com/6uoa0p पर कोड की कोशिश मैं भी यही परिणाम प्राप्तसाझा पॉइंटर तर्क अस्पष्टता

#include <memory> 

class Base{}; 
class Derived : public Base {}; 
class ExtraDerived : public Derived {}; 


bool IsBase(Base*){ return true; } 
bool IsBase(Derived*){ return false; } 

bool IsBase(std::shared_ptr<Base>){ return true; } 
bool IsBase(std::shared_ptr<Derived>){ return false; } 

int main() 
{ 
    auto derived = std::make_shared<Derived>(); 
    auto extra_derived = std::make_shared<ExtraDerived>(); 
    // works 
    auto raw_result_derived = IsBase(derived.get()); 
    auto raw_result_extra_derived = IsBase(extra_derived.get()); 
    auto shared_result_derived = IsBase(derived); 
    // doesn't work 
    auto shared_result_extra_derived = IsBase(extra_derived); 
} 

मैं: "अतिभारित समारोह के लिए अस्पष्ट कॉल त्रुटि C2668: 'IsBase'" उदाहरण के कोड देखें ।

यह वांछित व्यवहार की तरह प्रतीत नहीं होता है (क्योंकि यह 'कच्चे' सामान के लिए काम करता है)। क्या यह templating की एक सीमा है, क्या कोई और कारण है कि यह काम नहीं करता है या यह एक बग है? और मैं इसे कम से कम बदसूरत तरीके से कैसे काम कर सकता हूं?

सबसे अच्छा मैं के साथ आ सकते हैं

//ugly workaround 
bool IsBase(std::shared_ptr<Base>, Base*){ return true; } 
bool IsBase(std::shared_ptr<Derived>, Derived*){ return false; } 
template<typename T> bool IsBase(std::shared_ptr<T> input) 
{ 
    return IsBase(input, input.get()); 
} 
+4

:

हालांकि, आप अभी भी अपने भार के कुछ SFINAE की कमी का उपयोग करके ठीक कर सकते हैं? केवल बेस फ़ंक्शन प्रदान करें, यह खुशी से व्युत्पन्न क्लास पॉइंटर स्वीकार करेगा। यदि आप व्युत्पन्न क्लास ऑब्जेक्ट्स को पकड़ना चाहते हैं, तो आपकी विधि वैसे भी काम नहीं करेगी क्योंकि इसे सही करने के लिए फ़ंक्शन तर्क के डायनामिक प्रकार पर प्रेषण की आवश्यकता होगी। यदि प्रोग्रामर पूरी तरह से पास करने से पहले 'Ptr ' 'Ptr 'में परिवर्तित हो जाता है, तो यह ओवरलोडिंग दृष्टिकोण टूट जाता है। –

+0

@ जोहान्सचैब-लीटब मैंने उस स्थिति के बारे में नहीं सोचा था। मुझे जो चाहिए वह पुनर्विचार करना पड़ सकता है। – Barabas

उत्तर

4

यह वह जगह है templating की एक सीमा है, वहाँ एक और कारण है कि यह काम नहीं करता है या यह एक बग है है?

नहीं, यह एक बग नहीं है। दरअसल ऐसा लगता है कि आपने स्मार्ट पॉइंटर्स का एकमात्र नुकसान उठाया है: std::shared_ptr<base>std::shared_ptr<derived> से std::shared_ptr<extra_derived> से बनाया जा सकता है, लेकिन इनमें से कोई भी दो रूपांतरण अनुक्रम दूसरे की तुलना में बेहतर नहीं है (दो उपयोगकर्ता-परिभाषित रूपांतरण अनुक्रमों के समान लंबाई)। क्यों आपको लगता है कि चाहते हैं

#include <type_traits> 

// Selected for `std::shared_ptr<Base>` 
template<typename T, typename std::enable_if< 
    std::is_same<T, Base>::value>::type* = nullptr> 
bool IsBase(std::shared_ptr<T>){ return true; } 

// Selected for `std::shared_ptr<T>` where T is a class derived from Base, 
// but not Base itself 
template<typename T, typename std::enable_if< 
    std::is_base_of<Base, T>::value && 
    !std::is_same<T, Base>::value 
    >::type* = nullptr> 
bool IsBase(std::shared_ptr<T>){ return false; } 
+0

अफसोस की बात यह वीएस2012 पर काम नहीं करती है, लेकिन भविष्य में यह होना चाहिए। यह इस साधारण मामले के लिए काम करता है, लेकिन अगर अलग-अलग व्युत्पन्न कक्षाओं के लिए मेरे पास अधिक अधिभार था तो यह एक समस्या बन सकती है। मुझे इस बारे में सोचना होगा कि क्या मैं वास्तव में इस तरह के कार्यों को देखना चाहता हूं या मेरे प्रश्न पर जोहान्सचैब-लिटब की टिप्पणी पर विचार नहीं करना चाहता हूं। – Barabas

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