2013-06-07 6 views
16

इस मुद्दे पर कुछ बार चर्चा की गई है लेकिन मैंने पाया है कि सभी समाधान या तो काम नहीं किया है या बढ़ावा के स्थिर जोर पर आधारित थे। मेरी समस्या सरल है। मेरे पास एक कक्षा है, और मैं केवल वास्तविक प्रकार (डबल और फ्लोट) की अनुमति देना चाहता हूं। मैं एक संकलन-समय त्रुटि चाहता हूं यदि मैं कक्षा को फ्लोट या डबल के अलावा किसी अन्य प्रकार के साथ चालू करने का प्रयास करता हूं। मैं विजुअल सी ++ का उपयोग कर रहा हूं 11. यहां मैंने जो कोशिश की है:मैं टेम्पलेट क्लास को कुछ अंतर्निर्मित प्रकारों तक कैसे प्रतिबंधित करूं?

template <typename RealType> 
class A 
{ 
    // Warning C4346 
    static_assert(std::is_same<RealType, double>::value || std::is_same<RealType, float>::value); 
} 


template <typename RealType> 
class A 
{ 
    // Error C2062: type 'unknown' unexpected 
    static_assert(decltype(RealType) == double || decltype(RealType) == float); 
} 

कोई विचार? अग्रिम में धन्यवाद!

+1

पहला सवाल है, यह फर्क पड़ता है है? यदि आप किसी अन्य प्रकार के साथ टेम्पलेट को तुरंत चालू करते हैं, और इस प्रकार का इलाज नहीं किया जा सकता है जिस तरह से टेम्पलेट इसका इलाज करने की अपेक्षा करता है, संकलन विफल हो जाएगा। और यदि यह कर सकता है, * केवल * उन दो प्रकारों को प्रभावी ढंग से बहिष्कृत करने की इजाजत देता है ... कहें ... बिगडिसीमल जैसे एक प्रकार। – cHao

+0

विज़ुअल स्टूडियो वास्तव में एक चेतावनी जारी करता है जब static_assert विफल रहता है, और कोई त्रुटि नहीं? एक बग की तरह लगता है। –

+0

यह भी देखें [सी ++ टेम्पलेट्स जो केवल कुछ प्रकार स्वीकार करते हैं] (http://stackoverflow.com/q/874298/) और [सबक्लास को सी ++ टेम्पलेट पैरामीटर प्रतिबंधित करें] (http://stackoverflow.com/q/3175219)।वे सी ++ 11 की भविष्यवाणी करते हैं, लेकिन वे किसी और के लिए एक अच्छा मार्कर बना सकते हैं। – jww

उत्तर

12

एक समाधान मैंने देखा है std::enable_if एक प्रकार के उपनाम में उपयोग करना है। की तरह कुछ:

using value_type = typename std::enable_if< 
        std::is_same<float, RealType>::value || 
        std::is_same<double, RealType>::value, 
        RealType 
       >::type; 

value_type केवल मौजूद RealType बिल्कुल float या double है। अन्यथा, प्रकार अपरिभाषित है और संकलन विफल रहता है।

मैं प्रकार के साथ बहुत सख्त होने के बारे में चेतावनी दूंगा, हालांकि। टेम्पलेट्स उतने शक्तिशाली हैं जितना कि वे आंशिक रूप से हैं क्योंकि बतख टाइपिंग का मतलब है कि किसी भी प्रकार का उपयोग जिस तरीके से आप करना चाहते हैं, उसका उपयोग किया जाएगा। अस्वीकृत प्रकारों के लिए अस्वीकार करने वाले प्रकार आम तौर पर आपको ज्यादा लाभ नहीं पहुंचाते हैं, और चीजों को कम लचीला बना सकते हैं। उदाहरण के लिए, आप एक बड़े-दशमलव प्रकार की तरह अधिक सटीकता वाले प्रकार का उपयोग करने में सक्षम नहीं होंगे।

+0

वह, और यदि आपको केवल दो विशेषज्ञताओं की आवश्यकता है, तो अच्छा पुराना ओओ और रनटाइम पॉलीमोर्फिज्म एक बेहतर विचार हो सकता है (कम से कम विचार करने योग्य)। –

+0

SFINAE वास्तव में अच्छा है जब आप बाद में टेम्पलेट के अधिक विशेषज्ञ बनाना चाहते हैं :) हालांकि, यदि ज़े सुनिश्चित है कि कोई अन्य विशेषज्ञता कभी नहीं होगी, 'static_assert' अर्थपूर्ण त्रुटि संदेशों को प्रदर्शित करने की अनुमति देता है (क्योंकि SFINAE अक्सर मेरी आंखों को चोट पहुंचाते हैं)। 'Static_assert (झूठा," अच्छा संदेश ") के साथ – Morwenn

26

अपने पहले उदाहरण में, static_assert, एक दूसरा पैरामीटर जो एक स्ट्रिंग शाब्दिक होगा लेना चाहिए अन्यथा यह विफल समझा है (संपादित करें: छोड़ने दूसरा पैरामीटर के बाद से सी ++ 17 कानूनी है)। और यह दूसरा तर्क डिफ़ॉल्ट नहीं किया जा सकता है।

आपका दूसरे उदाहरण कई कारणों से गलत है:

  • decltype, एक अभिव्यक्ति पर इस्तेमाल किया जा करने के लिए एक प्रकार पर नहीं है।
  • आप == के साथ प्रकारों की तुलना नहीं कर सकते हैं, ऐसा करने का सही तरीका यह है कि आप std::is_same के साथ अपने पहले प्रयास में प्रयास करें।

तो, आप क्या हासिल करने की कोशिश कर रहे हैं करने के लिए सही तरीका है:

#include <type_traits> 

template <typename RealType> 
class A 
{ 
    static_assert(std::is_same<RealType, double>::value || std::is_same<RealType, float>::value, 
       "some meaningful error message"); 
}; 

इसके अलावा, मुझे यकीन है कि आप चल अंक मूल्यों के लिए अपने टेम्पलेट कसना करने की कोशिश कर रहे हैं। ऐसा करने के लिए है, तो आप विशेषता std::is_floating_point उपयोग कर सकते हैं:

#include <type_traits> 

template <typename RealType> 
class A 
{ 
    static_assert(std::is_floating_point<RealType>::value, 
       "class A can only be instantiated with floating point types"); 
}; 

और एक बोनस के रूप में, this online example ले।

5

इस तरह यह भी विभिन्न प्रकारों के लिए विशेषज्ञता की अनुमति देता है:

template<typename T, typename Enable = void> 
class A { 
/// Maybe no code here or static_assert(false, "nice message"); 
}; 

/// This specialization is only enabled for double or float. 
template<typename T> 
class A<T, typename enable_if<is_same<T, double>::value || is_same<T, float>::value>::type> { 

}; 
+1

; 'कार्यक्रम बीमार है, कोई निदान आवश्यक नहीं है। Http://stackoverflow.com/questions/30078818/static-assert- पर निर्भर-on-non-type-template-parameter- अलग- व्यवहार-on-gc पहले समस्या वास्तव में अधिक जटिल लगती है, लेकिन रेखांकित कारण है आपके उदाहरण के रूप में सरल। – bolov

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