2015-05-17 10 views
5
template<typename T, typename U = void> 
struct S { /* static_assert(0, "type unsupported"); */ }; 
template<typename T> 
struct S<T, typename std::enable_if<std::is_integral<T>::value, void>::type> { 
    void foo() {} 
}; 
... 
S<int> i; 
i.foo(); 
S<double> d; 
// d.foo(); 

मैं उम्मीद कर रहा होगा कि "मास्टर टेम्पलेट" कभी नहीं int के मामले के लिए instantiated किया जाएगा, लेकिन अगर मैं static_assert uncomment, S<int> इन्स्टेन्शियशन असफल हो जायेगी। यहां तक ​​कि एक अकेला typedef S<int> Si; संकलित करने में विफल रहेगा। (जीसीसी 4.9.2 सिग्विन)static_assert

foo() कॉल पर असफल होने के लिए S<double> के लिए मुझे प्राप्त करने का लक्ष्य नहीं है, लेकिन टेम्पलेट के तत्काल होने पर, और एक सार्थक त्रुटि संदेश के साथ। मुझे पता है कि मैं मास्टर टेम्प्लेट में typename T::nonexistent_type t; जैसे कुछ कर सकता हूं जो संकलन के लिए टेम्पलेट को रोक देगा, लेकिन यह static_assert संदेश से कम होगा। (नोट: मास्टर टेम्पलेट में एक समारोह परिभाषा के दायरे में static_assert डाल अभी भी S<int> के लिए संकलन में विफल रहता है)

static_assert क्यों असफल है, भले ही उस टेम्पलेट instantiated नहीं है? क्या यह मानक द्वारा अनिवार्य (या शायद "अनिर्दिष्ट") है? क्या static_assert जिस तरह से मैं चाहता हूं उससे असफल होने का कोई तरीका है?

+0

देखें ['static_assert' हमेशा क्यों आ जाता है?] (Http://stackoverflow.com/q/27738971/3953764) –

उत्तर

7

static_assert में अभिव्यक्ति एक टेम्पलेट पैरामीटर पर निर्भर होना चाहिए यदि आप केवल तत्काल समय-समय पर होना चाहते हैं। यह मानक द्वारा गारंटीकृत है- कार्यान्वयन (लेकिन कोई दायित्व नहीं है) टेम्पलेट्स में static_assertion एस जांचें जो किसी भी टेम्पलेट पैरामीटर पर निर्भर नहीं हैं।

आपका कोड की तरह

template<typename T> struct S { 
    static_assert(std::is_integral<T>::value, "type unsupported"); 
    void foo() {} 
}; 

यह स्पष्ट रूप से संकलक करने के लिए अभिव्यक्ति और टेम्पलेट पैरामीटर के बीच निर्भरता संचार कुछ करने का एक अजीब राउंडअबाउट तरीका है, और अब तक स्पष्ट और साथ ही पढ़ने में आसान है। अगर आप अभिन्न प्रकारों के लिए या गैर-अभिन्न प्रकारों के लिए असफल होने के लिए संकलन चाहते थे तो मैं वास्तव में काफी समझ नहीं पाया।

+0

मैंने अपनी मूल समस्या को समस्या का प्रदर्शन करने के लिए सबसे सरल रूप से कम कर दिया है। मुझे संकलन समय पर विभिन्न मामलों को समझने की ज़रूरत है और कुछ और आंशिक विशेषज्ञता से मेल नहीं खाती है। इस प्रकार उपरोक्त कोड। मुझे अभी एहसास हुआ कि * किसी भी * निर्भरता प्रकार पर निर्भरता: 'static_assert :: value && 0," असमर्थित टाइप करें "> 'जो मैं चाहता हूं वह करता है। (लगभग - 'टाइपिफ एस एसडी अभी भी संकलित है, लेकिन' एसडी डी घोषणा विफल हो जाती है, इसलिए यह ठीक है) – Irfy

+0

@lrfy: फिर सबसे आसान काम करना 'is_valid' विशेषता है जो विभिन्न आंशिक विशेषज्ञता मामलों को जोड़ती है और सशर्त – Puppy

+0

@Puppy के रूप में इसका उपयोग करें - मेरे पास बस कुछ ऐसा ही था। आपका 'is_valid' समाधान कभी-कभी केवल एक के बजाय सभी विशेषज्ञता के साथ दो टेम्पलेट्स लिखने का मतलब है - और पूरी तरह से उस व्यक्ति से बेहतर त्रुटि संदेश प्राप्त करने के लिए। यह अव्यवस्था का एक उचित हिस्सा हो सकता है, और सभी विशेषज्ञता मामलों को डुप्लिकेट करने का मतलब है कि वे आसानी से असंगत हो सकते हैं (हालांकि AFAICT जो कभी भी रन-टाइम बग का नेतृत्व नहीं करना चाहिए)। 'Static_assert' स्थिति लिखना अजीब तरह से एक बेहतर दृष्टिकोण हो सकता है, और संभवतः यह' dependent_false 'टेम्पलेट होने योग्य होगा। – Steve314

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