2013-06-07 22 views
7

के साथ विफल रहता है मैं समझने की कोशिश कर रहा हूं कि सी ++ (11) <type_traits> का उपयोग कैसे करें।टेम्पलेट तर्क प्रकार कटौती सी ++ 11 <type_traits>

यहाँ मेरी तुच्छ परीक्षण कार्यक्रम

#include <type_traits> 

template<class U, class S> 
inline U add(typename std::enable_if<std::is_unsigned<U>::value,U>::type a, 
      typename std::enable_if<std::is_signed <S>::value,S>::type b) 
{ 
    return a + b; 
} 

int main(int argc, const char * argv[], const char * envp[]) 
{ 
    unsigned int ui; 
    int i; 
    auto a = add(ui, i); 
    return 0; 
} 

है जब मैं कोई सुराग नहीं क्यों जीसीसी टेम्पलेट पैरामीटर U अनुमान नहीं कर सकता है के रूप में

/home/per/f.cpp: In function ‘int main(int, const char**, const char**)’: 
/home/per/f.cpp:15:23: error: no matching function for call to ‘add(unsigned int&, int&)’ 
    auto a = add(ui, i); 
        ^
/home/per/f.cpp:15:23: note: candidate is: 
/home/per/f.cpp:5:10: note: template<class U, class S> U add(typename std::enable_if<std::is_unsigned<U>::value, U>::type, typename std::enable_if<std::is_signed<S>::value, S>::type) 
inline U add(typename std::enable_if<std::is_unsigned<U>::value,U>::type a, 
     ^
/home/per/f.cpp:5:10: note: template argument deduction/substitution failed: 
/home/per/f.cpp:15:23: note: couldn't deduce template parameter ‘U’ 
    auto a = add(ui, i); 
        ^

जीसीसी 4.8.1 यह त्रुटियों के साथ संकलित। कोई भी जानता है कि मेरे कोड में कौन सी जानकारी गुम है, इस तरह मैं सी ++ 11 में एक प्रोग्राम लिखता हूं जो पहले हस्ताक्षर के रूप में एक हस्ताक्षरित अभिन्न प्रकार लेता है और दूसरे के रूप में हस्ताक्षर किए गए अभिन्न प्रकार को लेता है?

+0

आप decuce नहीं कर सकते हैं प्रकार के एक योग्यता के 'छोड़ ::'। –

+0

** 14.8.2.5 किसी प्रकार से टेम्पलेट तर्कों को कम करना [temp.deduct.type] ** 5 गैर-कटौती वाले संदर्भ हैं: - एक प्रकार का नेस्टेड-नाम-विशिष्टता जो क्वालिफ़ी-आईडी का उपयोग करके विशिष्ट थी। – TemplateRex

+0

सभी अच्छी टिप्पणियों और उत्तरों के लिए धन्यवाद! –

उत्तर

13

typename std::enable_if<std::is_unsigned<U>::value,U>::type एक deducible संदर्भ नहीं है। इस से U को कम करने के लिए संकलक को std::enable_if के रिवर्स ऑपरेशन को लागू करने की क्षमता की आवश्यकता होगी। यह बहुत कठिन नहीं लग रहा है, यह सच है, लेकिन ऐसा इसलिए है क्योंकि आप enable_if जैसी साधारण चीज़ के बारे में बात कर रहे हैं। प्रत्येक विशेषता के लिए यह असंभव होगा, इसलिए सी ++ बस इसे ठंडा करता है और किसी भी प्रकार का अजीब नियम अपवाद नहीं बनाता है: यह सामान्य रूप से कटौती नहीं करता है, यह इस में कटौती नहीं करता है।

आप इसे बजाय इस तरह से कर सकते हैं:

template<class U, class S, 
     EnableIf<std::is_unsigned<U>, std::is_signed<S>>...> 
     // see http://flamingdangerzone.com/cxx11/2012/06/01/almost-static-if.html 
U add(U a, S b) 

या compilers में है कि उस शैली का समर्थन नहीं करते ठीक से तुम सिर्फ एक अतिरिक्त डिफॉल्ट तर्क जोड़ सकते हैं:

template<class U, class S> 
U add(U a, S b, 
     typename std::enable_if<std::is_unsigned<U>::value 
      && std::is_signed<S>::value,void>::type* = nullptr) 

... या रिटर्न प्रकार के साथ गड़बड़ाना।

template<class U, class S> 
typename std::enable_if<std::is_unsigned<U>::value 
    && std::is_signed<S>::value,U>::type 
add(U a, S b) 
+0

वाह ...यह क्या कर रहा है? 'typename std :: enable_if :: मान && std :: is_signed :: मान, शून्य> :: प्रकार * = nullptr'। पॉइंटर के लिए rvalue? –

2

"नेस्टेड टाइपपीफ" अभिव्यक्ति से टेम्पलेट पैरामीटर को कम करना संभव नहीं है। यही है, Usome_template<U> से, लेकिन some_template<U>::type से नहीं करना संभव है।

कंपाइलर संभवत: some_template के सभी (अनंत!) इंस्टेंटेशन की गणना नहीं कर सकता है और देखें कि उनमें से कौन सा नेस्टेड टाइपपीफ वास्तविक तर्क प्रकार के बराबर है।

3

आपको पहले से पहले घटाएं, आप इस प्रकार के कारणों का कारण बन सकते हैं!

यह होना चाहिए:

template <typename U, typename S> 
typename std::enable_if<std::is_unsigned<U>::value && 
         std::is_signed<S>::value>, U>::type 
add(U u, S s) 
{ 
    // ... 
} 
7

आप संकलक U और S अनुमान करने का मौका दे रही है नहीं कर रहे हैं। इस प्रकार आप अपने समारोह को फिर से लिखने सकते हैं, और टेम्पलेट पैरामीटर सूची में SFINAE चेकों के लिए कदम:

template<class U, class S, 
    typename std::enable_if<std::is_unsigned<U>::value && 
          std::is_signed <S>::value 
     >::type* = nullptr> 
inline U add(U a, S b) 
{ 
    return a + b; 
} 

यहाँ एक live example है।

2

प्रयास करें:

template<class U, class S> 
typename std::enable_if<std::is_unsigned<U>::value && std::is_signed<S>,U>::type 
add(U a , S b) 
{ 
    return a + b; 
} 
+0

व्यक्तिगत रूप से, मैं वापसी प्रकार पर enable_if लिखना पसंद करता हूं, क्योंकि यह फ़ंक्शन घोषणा को स्पष्ट करता है। और, इसके अलावा, टेम्पलेट कटौती कार्य (आपके मामले में) बनाता है। – Manu343726

+0

** इनलाइन ** कीवर्ड के उपयोग से बचें। सी ++ कंपाइलर हर फंक्शन को रेखांकित करता है अगर ऐसा लगता है कि यह अधिक कुशल है। भले ही आपने ** इनलाइन ** लिखा हो या नहीं। और, यहां तक ​​कि आप ** इनलाइन ** डालते हैं, यदि संकलक सोचता है कि उस कार्य में इनलाइन कार्य कुशल नहीं है, तो यह फ़ंक्शन को इनलाइन नहीं करेगा। तो, ** इनलाइन ** लिखें नहीं। *** आप कंपाइलर *** की तुलना में बेहतर अनुकूलक नहीं हैं ***। सरल और स्पष्ट कोड लिखें और संकलक को अपना काम करने दें। – Manu343726

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