2015-09-08 9 views
7

मेरे पास एक टेम्पलेट फ़ंक्शन है जहां एक enum प्रकार को इसके अंतर्निहित प्रकार में परिवर्तित किया जाता है जो ठीक काम करता है, लेकिन मैंने एक अधिभार लिखा है जिसे एक अभिन्न संख्या लेनी चाहिए और इसे वापस करना चाहिए और यह देना मुझे एक त्रुटि है कि int एक गणना प्रकार नहीं है। मेरे टेम्पलेट में, इसे फ़िल्टर किया जाना चाहिए था। गलत क्या है?प्रकार से उसी प्रकार से "रूपांतरण" त्रुटि

template <typename TT> 
    static constexpr auto get_value(TT t) 
    -> typename std::enable_if<!std::is_enum<TT>::value, TT>::type 
    { 
     return t; 
    } 

    template <typename TT> 
    static constexpr auto get_value(TT t) 
    -> typename std::enable_if<std::is_enum<TT>::value, typename std::underlying_type<TT>::type>::type 
    { 
     return (typename std::underlying_type<TT>::type)t; 
    } 

Demo

+1

मैं अगर 'underlying_type' SFINAE के अनुकूल है पता नहीं है, लेकिन वहाँ एक [वैकल्पिक हल] (http://coliru.stacked-crooked.com/a/e7f1dd3b75c8d9c2) कि –

+0

क्या है? मुझे लगता है कि यह काम करता है, लेकिन यहां क्या चल रहा है जो इसे काम करता है? और SFINAE द्वारा दोस्ताना 'अंतर्निहित_टाइप' क्यों नहीं होगा? – Adrian

+1

'std :: underlying_type का तत्काल :: टाइप' स्थगित कर दिया गया है, ताकि 'enable_if' पहले विफल हो सके। * SFINAE- अनुकूल * मेरा मतलब है कि किसी भी प्रतिस्थापन विफलता केवल तत्काल संदर्भ में होती है (यदि यह 'अंतर्निहित_type' के अंदर होती है तो यह स्वयं SFINAE- अनुकूल नहीं है)। –

उत्तर

4

std::underlying_type<TT>::type में std::enable_if भी std::is_enum<TT>::value हालांकि है falsefalse के रूप में कोई त्रुटि नहीं है मूल्यांकन किया जा रहा है:

यहाँ टेम्पलेट कोड है। चूंकि एक गैर गणना प्रकार का मूल्यांकन किया जा रहा है क्योंकि यह एक त्रुटि उत्पन्न कर रहा है। यदि हम टेम्पलेट पैरामीटर में SFINAE को स्थानांतरित करते हैं तो हम वांछित ओवरलोड प्राप्त कर सकते हैं और फिर भी सही प्रकार वापस कर सकते हैं।

template <typename TT, typename std::enable_if<!std::is_enum<TT>::value, TT>::type* = nullptr> 
static constexpr auto get_value(TT t) -> TT 
{ 
    return t; 
} 

template <typename TT, typename std::enable_if<std::is_enum<TT>::value>::type* = nullptr> 
static constexpr auto get_value(TT t) -> typename std::underlying_type<TT>::type 
{ 
    return (typename std::underlying_type<TT>::type)t; 
} 

आप इसे इस Live Example

+0

तो बस यह सुनिश्चित करने के लिए कि मैं इसे सही ढंग से समझ रहा हूं, दूसरा टेम्पलेट पैरामीटर 'void *' प्रकार का एक अनाम पैरामीटर है, जो enum प्रकार है (जो मैं चाहता हूं उसके आधार पर) जिसके परिणामस्वरूप बनाया जा रहा है और एक गैर इकाई मैं क्या चाहता हूं और फिर खारिज कर दिया जाएगा? – Adrian

+0

@Adrian यदि 'std :: enable_if'' टाइप' सफल होता है तो शून्य है और फिर हम SFINAE – NathanOliver

+0

@dyp के लिए टाइप के पॉइंटर को 'nullptr' पर सेट कर सकते हैं। मैंने उत्तर संपादित किया है। इसे अब वास्तविक कारण को संबोधित करना चाहिए। – NathanOliver

4

में काम कर T साथ std::underlying_type<T> का दृष्टांत है कि एक enum प्रकार नहीं है प्रयास कर करके, आप एक आवश्यकता है कि स्टैंडर्ड टेम्पलेट पैरामीटर T पर लगाता उल्लंघन कर रहे हैं देख सकते हैं:

§ 20.10.7.6 [meta.trans.other]/टेबल 57:

 Template   |   Condition   |  Comments 
------------------------+---------------------------+----------------------- 
template <class T>  | T shall be an enumeration | The member typedef 
struct underlying_type; | type (7.2)    | type shall name 
         |       | the underlying type 
         |       | of T. 

यहाँ एक वैकल्पिक दृष्टिकोण है कि अगर एक किसी भी अतिरिक्त टेम्प्लेट पैरामीटर पसंद नहीं करता:

template <typename TT> 
static constexpr auto get_value(TT t) 
    -> typename std::enable_if<!std::is_enum<TT>::value, TT>::type 
{ 
    return t; 
} 

template <typename TT> 
static constexpr auto get_value(TT t) 
    -> typename std::enable_if<std::is_enum<TT>::value 
          , std::underlying_type<TT> 
       >::type::type 
{ 
    return (typename std::underlying_type<TT>::type)t; 
} 

इस तरह, std::underlying_type<TT> की इन्स्टेन्शियशन तक std::enable_if में हालत true का मूल्यांकन टाल जाता है, क्योंकि एक नेस्टेड type परिभाषा अनुरोध किया जाता है std::enable_if<B,T>::type रिटर्न के लिए।

DEMO

+0

तो, आवश्यकता केवल तभी जरूरी है जब आपको 'std :: underlying_type :: टाइप' टाइप करें लेकिन 'std :: underlying_type ' के लिए आवश्यक नहीं है? ऐसा क्यों है? – Adrian

+1

@Adrian 'std :: underlying_type 'तत्काल नहीं किया जाता है जब केवल एक प्रकार के टेम्पलेट तर्क के रूप में उपयोग किया जाता है –

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