2012-12-31 22 views
6

इस कोड को सबसे compilers में संकलित करने के लिए विफल रहता है, लेकिन पहली बार में मैं सहज उम्मीद SFINAE मुझे की रक्षा के लिए:SFINAE, कटौती बनाम इन्स्टेन्शियशन

:

typedef void (*A)(); 

template < typename T > 
struct a_metafun { typedef typename T::type type; }; 

template < typename T > 
typename a_metafun<T>::type f(T) {} 

template < typename T> 
void f(T(*)()) {} 

int main() { f(A()); } 

मैं कम से कम दो तरीकों से इस समस्या को ठीक कर सकते हैं

template < typename T > typename T::type f(T) {}

2) को परिभाषित "a_metafun" ऐसी है कि वह टी का विश्लेषण करती है और प्रकार होता है, तो टी से एक है और मैं नहीं करता है: 1) करने के लिए) की "metafun" च (परिभाषा बदलें वास्तव में क्या स्थिति SFINAE लागू कर सकते हैं के तहत 14.8.2 (सी ++ 03) को देख पर

BOOST_MPL_HAS_XXX_TRAIT_DEF(type) 

typedef < template T, bool = has_type<T>::value > 
struct a_metafun { }; 

typedef < template T > 
struct a_metafun<T, true> { typedef typename T::type type }; 

यह मेरे लिए लग रहा है जैसे कि यह निर्दिष्ट करता है: च यह नहीं है ... लेकिन बिना किसी त्रुटि के किसी भी तरह को दर्शाता है। क्या देखने के लिए कोई बेहतर जगह है? पहले से ही कट किए गए टेम्पलेट के तत्कालता में विफलता, किसी अन्य की कटौती के दौरान भी, इस सूची में शामिल नहीं लगती है।

एक और दिशा जिसे मैंने यह अवैध बनाने के लिए लिया है, यह है कि a_metafun की कटौती पहले ही हो चुकी है और इसके अंदरूनी हिस्सों का त्वरण त्रुटि उत्पन्न कर रहा है। SFINAE तत्काल के दौरान लागू नहीं होता है लेकिन केवल कटौती के दौरान, या क्या मैं वहां गलत हूं? हालांकि, दूसरे मामले में, a_metafun सही ढंग से किया जा रहा है, और अच्छी तरह से गठित किया गया है लेकिन इसमें बस "टाइप" परिभाषा नहीं है, जिसका अर्थ है कि इसे चालू करने का प्रयास करने वाला टेम्पलेट प्रतिस्थापन के कारण विफल रहा है।

असल में मैं सोच रहा हूं कि मानक में क्या व्यवहार देख रहा है, जो मैं देख रहा हूं। प्रत्येक कंपाइलर मैंने शिकायत की कोशिश की है, यहां तक ​​कि आओ। मेरा मानना ​​है कि वे ऐसा करने में सही हैं, मैं पूरी तरह से क्यों नहीं जानता हूं कि क्यों।

तो, विशेषज्ञ ... क्या है? प्रकार की तात्कालिकता, एफ() में कटौती के संदर्भ में भी एसएफआईएनएई बहिष्करण के बजाय त्रुटि का कारण बनती है?

+0

मुझे लगता है कि सी ++ 11 में असफल चाहिए, सी ++ 03 यद्यपि में नहीं: यहाँ एक सक्रिय मुद्दा है। SFINAE नियम (या बल्कि * शब्द *) सी ++ 11 में थोड़ा बदल गया है। – Nawaz

उत्तर

2

SFINAE तुम वहाँ रक्षा नहीं करेंगे, त्रुटि होताके बाद प्रकार कटौती। बहरहाल, यह काम करना चाहिए:

template < typename T, typename Type = typename T::type > 
struct a_metafun { typedef Type type; }; 

एक डिफ़ॉल्ट टेम्पलेट पैरामीटर हम इस प्रतिस्थापन समय हो करने के लिए कारण में T::type में जाकर करके, और उस समय SFINAE किक में

संपादित करें:। सोच के बाद कुछ और, मुझे बिल्कुल यकीन नहीं है कि आपका वर्तमान कार्यान्वयन क्यों विफल रहता है। मुझे लगता है क्योंकि a_metafunमें सदस्य सदस्य type है, जो संकलन त्रुटि का कारण बनता है; यह अलग होगा यदि a_metafun में सदस्य प्रकार type नहीं था।

+0

मेरा उत्तर देखें कि यह C++ 11 में क्यों विफल रहता है। – Nawaz

4

सी ++ 03 विनिर्देशन में, एसएफआईएनएई का नियम थोड़ा अस्पष्ट है, जिससे संकलक लेखकों को लंबाई पर जाने की अनुमति मिलती है ताकि SFINAE में परिणामस्वरूप विफलता हो सके। प्रासंगिक पाठ §14.8.2/2 सी ++ 03 से कहते हैं,

- [...] तो टेम्पलेट पैरामीटर में या अमान्य प्रकार में समारोह टेम्पलेट परिणामों के समारोह प्रकार में एक प्रतिस्थापन, प्रकार कटौती विफल रहता है [...]

यह आगे विफलता के कुछ कारण बताता है, लेकिन उनमें से कोई भी वास्तव में कहता है कि प्रतिस्थापन विफलता को SFINAE के रूप में क्यों माना जाना चाहिए। तो मुझे लगता है कि आपका कोड C++ 03 में ठीक काम कर सकता है (या नहीं, इस पर निर्भर करता है कि संकलक लेखक पाठ की व्याख्या कैसे करते हैं। यह वैसे भी मुझे भ्रमित कर रहा है)।

लेकिन सी ++ 11 में शब्दों को अस्पष्टता को दूर करने में सुधार किया गया है। यह §14.8.2/8,

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

अवधि "तत्काल संदर्भ" दिलचस्प है, और मैं इसे अपनी स्थिति के लिए लागू होता है। अधिक विशेष रूप से, मेटा-फ़ंक्शन a_metafun में प्रतिस्थापन विफलता को फ़ंक्शन-प्रकार के "तत्काल संदर्भ" नहीं माना जाता है। यह सी ++ 11 में खराब है, न कि SFINAE।

"तत्काल संदर्भ" की परिभाषा सी ++ 11 में पर्याप्त स्पष्ट नहीं है।

+1

वास्तव में दिलचस्प है! मुझे _SFINAE_ में इस परिवर्तन के बारे में पता नहीं था। धन्यवाद –

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

  • कोई संबंधित समस्या नहीं^_^