2015-10-01 38 views
5

के लिए एक प्रकार nullptr दें निम्नलिखित स्निपेट मान लीजिए:,टेम्पलेट कटौती

template <class T> 
void fct(T* a, T* b){ 
    // do something 
} 

A a; 
fct(&a, nullptr); // Problem here! 

इस मुसीबत बना देता है के बाद से कॉल तर्क प्रकार A* और nullptr_t और इतने संकलक के हैं टेम्पलेट पैरामीटर T अनुमान नहीं कर सकते।

आम तौर पर, मैं कई विचारों की कल्पना कैसे हल करने के लिए इस कर सकते हैं:

  • परिभाषित A* b = nullptr और प्रयोग nullptr मामले
  • के लिए fct(&a, b)
  • fct के लिए एक तर्क के साथ एक अधिभार को परिभाषित करें उपयोग fct(&a, static_cast<A*>(nullptr))

या क्या कोई और साफ समाधान है, li एक "टाइप नलप्टर" की तरह कुछ बनाने के लिए?

template <class T, class U> 
void fct(T* a, U b){ 
    T* b2 = b; 
    // do something 
} 

A a; 
fct(&a, nullptr); 

यह fct की एक व्यापक उपयोग के लिए अनुमति देता है, लेकिन शायद यह है कि वास्तव में क्या आप चाहते हैं:

+0

आपकी इच्छित "टाइप नलप्टर" 'static_cast (nullptr) 'से अलग कैसे हो सकता है? – Petr

+2

आपका दूसरा विकल्प सबसे अच्छा शर्त जैसा दिखता है ... ओवरलोड (टेम्पलेट विशेषज्ञता) – basav

+0

आपने पहले ही प्रश्न में उत्तर दिया है ... पहला और तीसरा विकल्प समान या कम है: आपको टी * और नलप्टर की आवश्यकता नहीं है, इसलिए आप ' fct (& a, nullptr) ', और दूसरा इसे अनुमति देने के लिए एक स्पष्ट अधिभार का उपयोग करता है। मैं एक और जवाब की कल्पना नहीं कर सकता ... –

उत्तर

2

मैं भी निम्न समाधान सुझाव है।

उदाहरण के लिए, पर विचार

class A {}; 
class B : public A {}; 

... 
A a; 
B b; 
fct(&a, &b); // calls fct<A> 
// the following will not compile: 
// fct(&b, &a); 
1

आप नीचे दिए गए कोड का उपयोग कर सकते हैं:

#include <type_traits> 

template<class T> 
void f_impl(T*, T*) 
{ 
    std::cout << typeid(T).name() << "\n"; 
} 


template<class T, class U> 
void f(T l, U r) 
{ 
    static_assert((std::is_same<T, U>::value && std::is_pointer<T>::value) || 
        (std::is_same<T, std::nullptr_t>::value && std::is_pointer<U>::value) || // First non-null 
        (std::is_same<U, std::nullptr_t>::value && std::is_pointer<T>::value) // Second non-null 
        , ""); 

    using P = typename std::conditional<std::is_same<T, std::nullptr_t>::value, U, T>::type; 

    f_impl<typename std::remove_pointer<P>::type>(l, r); 
} 

int main() 
{ 
    int i; 
    f(&i, nullptr); 
    f(nullptr, &i); 
    // f(i, nullptr); // won't compile - non-pointer 
    f(&i, &i); 

    double d; 
    // f(&i, &d); // - won't compile 

} 

इस संस्करण परीक्षण एक nullptr (लेकिन दोनों), या के साथ दो संकेत के साथ f फोन करने की अनुमति देगा एक ही प्रकार के लिए। सी ++ 14 के साथ आप कुछ biolerplate को हटाने के लिए std::conditional_t, std::remove_pointer_t और std::is_null_pointer जैसी चीजों का भी उपयोग कर सकते हैं।

template <class T> 
void fct(T* a, std::remove_reference<T*>::type b) { 
+0

आपको 'f ' या 'f 'पर कॉल करने की आवश्यकता है, जो कि गैर-शून्य है; आपका वर्तमान संस्करण 'f 'कॉल करता है जब' f (nullptr, & i) 'के रूप में उपयोग किया जाता है। – Petr

+0

@Petr उस कोड के साथ और अधिक समस्याएं थीं। उनकी व्यवस्था करना। धन्यवाद! – Rostislav

5

बस दूसरा तर्क एक गैर निष्कर्ष निकाला संदर्भ, उदा बनाते हैं। तो बस विशेष रूप से उस मामले के लिए एक स्पष्ट अधिभार जोड़ें:

template <class T> 
void fct(T* a, std::nullptr_t b) { return fct<T>(a,static_cast<T*>(b)); } 

कोई ज़रूरत नहीं है कि के लिए कुछ टेम्पलेट तर्क class U है।

+0

दूसरे फ़ंक्शन तर्क के सामने 'टाइपनाम' गायब है? कोई भी नए और थोड़ा कम verbose'std :: remove_reference_t' का उपयोग कर सकता है। – user1735003

0

सवाल जैसा कि पहले ही कहा गया है, वास्तव में nullptr एक प्रकार का है:: std::nullptr_t

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