2011-01-21 13 views
18

को देखते हुए:पूर्णांक प्रकार के "हस्ताक्षरित-नेस" के आधार पर आंशिक टेम्पलेट विशेषज्ञता?

unsigned n; 
f(n); // warning: comparison n >= 0 is always true 

वहाँ किसी भी चालाक रास्ता तुलना n >= 0 जब T एक unsigned प्रकार है करने के लिए नहीं है:

template<typename T> 
inline bool f(T n) { 
    return n >= 0 && n <= 100; 
} 

जब एक unsigned प्रकार के साथ प्रयोग किया एक चेतावनी उत्पन्न करता है? मैंने आंशिक टेम्पलेट विशेषज्ञता जोड़ने की कोशिश की:

template<typename T> 
inline bool f(unsigned T n) { 
    return n <= 100; 
} 

लेकिन जीसीसी 4.2.1 पसंद नहीं है। (मुझे नहीं लगता था कि आंशिक टेम्पलेट विशेषज्ञता का प्रकार वैसे भी कानूनी होगा।)

+2

नोट समारोह टेम्पलेट्स, केवल पूर्ण विशेषज्ञता के लिए कोई आंशिक विशेषज्ञता नहीं है। उस ने कहा, पूर्ण विशेषज्ञता आमतौर पर फ़ंक्शन टेम्पलेट्स के लिए एक बुरा विचार है क्योंकि जो विशिष्ट हो जाता है, जो अधिभारित हो जाता है, और ओवरलोड लोड रिज़ॉल्यूशन का निर्धारण करने का निर्णय जटिल और जटिल है। शुक्र है, अधिभार और SFINAE (प्रतिस्थापन विफलता एक त्रुटि नहीं है) यहां पर्याप्त हैं। –

+0

मुझे इस पर क्लैंग 3.8 (या जीसीसी 8.0) से कोई चेतावनी नहीं मिली है। यदि मैं 'f' पर टेम्पलेट को हटा देता हूं तो मुझे यह मिलता है। क्या '-वैटोलॉजिकल-तुलना' का एक संस्करण है जो टेम्पलेट इंस्टॉलेशन को मानता है? – user2023370

उत्तर

22

आप is_unsigned प्रकार विशेषता के साथ enable_if उपयोग कर सकते हैं: अपने संकलक C++ 0x का समर्थन करता है या TR1 क्रमश: अगर

template <typename T> 
typename std::enable_if<std::is_unsigned<T>::value, bool>::type f(T n) 
{ 
    return n <= 100; 
} 

template <typename T> 
typename std::enable_if<!std::is_unsigned<T>::value, bool>::type f(T n) 
{ 
    return n >= 0 && n <= 100; 
} 

आप enable_if और std या std::tr1 नामस्थान में is_unsigned पा सकते हैं। अन्यथा, बूस्ट प्रकार के गुण पुस्तकालय, Boost.TypeTraits का कार्यान्वयन है। enable_if का बढ़ावा कार्यान्वयन थोड़ा अलग है; boost::enable_if_c TR1 और C++ 0x enable_if के समान है।

14

आप बिना हस्ताक्षर किए गए पूर्णांक के लपेटने वाले व्यवहार का लाभ उठा सकते हैं।

template<bool> struct bool_ { }; 

template<typename T> 
inline bool f(T n, bool_<false>) { 
    return n >= 0 && n <= 100; 
} 

template<typename T> 
inline bool f(T n, bool_<true>) { 
    return n <= 100; 
} 

template<typename T> 
inline bool f(T n) { 
    return f(n, bool_<(static_cast<T>(-1) > 0)>()); 
} 

चेतावनी से बचने के लिए >= 0 कहना महत्वपूर्ण नहीं है। निम्नलिखित जीसीसी चाल करने के लिए प्रकट होता है भी

template<typename T> 
inline bool f(T n) { 
    return (n == 0 || n > 0) && n <= 100; 
} 
+0

उस अंतिम चाल के लिए +1 – TonyK

0

आप unsigned प्रकार की तरह के लिए एक विशेष टेम्पलेट समारोह कार्यान्वयन को लागू कर सकते हैं:

template<class T> bool f(T val); 
template<> bool f<unsigned>(unsigned val); 

अद्यतन अहस्ताक्षरित झंडा

आप सभी के लिए अलग कार्यान्वयन लागू कर सकते हैं हस्ताक्षर किए गए प्रकार जिन्हें आप उपयोग करना चाहते हैं या bool ध्वज जोड़ें:

template <class T, bool U> bool f(T val) 
{ 
     if (U) 
       return val <= 100; 
     else 
       return (val >=0) && (val <= 100); 
} 

... 

cout << f<int, false>(1) << endl; 
cout << f<int, false>(-1) << endl; 
cout << f<char, true>(10) << endl; 
+0

इसके अलावा इसे सभी हस्ताक्षरित प्रकारों के लिए काम करना है: char, short, int, long। –

+0

आपका समाधान बहुत अधिक वर्बोज़ है जो अन्य "enable_if" (या समान कार्यक्षमता) का लाभ उठाते हैं। –

+1

आपका समाधान भी एकमात्र ऐसा प्रतीत होता है जिसे बढ़ावा देने के बिना सी ++ 03 में कार्यान्वित किया जा सकता है। यह मेरी किताब में एक स्पष्ट प्लस है। जब मैं इसे काम करने के लिए प्राप्त करता हूं तो मैं ऊपर हट जाऊंगा;) – Paul

1

क्या कोई चालाक तरीका तुलना नहीं है n = = 0 जब टी एक हस्ताक्षरित प्रकार है? मैंने आंशिक टेम्पलेट विशेषज्ञता जोड़ने की कोशिश की:

अनुकूलक को इस स्थिति का पता लगाने के बाद तुलना के लिए कोड छोड़ना चाहिए।

क्लैंग के लिए, चेतावनी को स्क्वैश करने के लिए -Wno-tautological-compare जोड़ें। जीसीसी/जी ++ के लिए, चेतावनी को स्क्वैश करने के लिए -Wno-type-limits जोड़ें।

आप एक संकलक का समर्थन करने वाले pragma diagnostic {push|pop} आप कर सकते हैं का उपयोग कर रहे हैं:

#if (GCC_VERSION >= 40600) || (LLVM_CLANG_VERSION >= 10700) || (APPLE_CLANG_VERSION >= 20000) 
# define GCC_DIAGNOSTIC_AVAILABLE 1 
#endif  

#if MSC_VERSION 
# pragma warning(push) 
# pragma warning(disable: 4389) 
#endif 

#if GCC_DIAGNOSTIC_AVAILABLE 
# pragma GCC diagnostic push 
# pragma GCC diagnostic ignored "-Wsign-compare" 
# if (LLVM_CLANG_VERSION >= 20800) || (APPLE_CLANG_VERSION >= 30000) 
# pragma GCC diagnostic ignored "-Wtautological-compare" 
# elif (GCC_VERSION >= 40300) 
# pragma GCC diagnostic ignored "-Wtype-limits" 
# endif 
#endif 

template<typename T> 
inline bool f(T n) { 
    return n >= 0 && n <= 100; 
} 

#if GCC_DIAGNOSTIC_AVAILABLE 
# pragma GCC diagnostic pop 
#endif 

#if MSC_VERSION 
# pragma warning(pop) 
#endif 

भी देखें Comparison is always false due to limited range…

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