2014-06-21 8 views
10

के बीच विभिन्न उत्पादन निम्न उदाहरण पर विचार करें:संकुचन पूर्णांक SFINAE में bool करने के लिए, जीसीसी और बजना

template<int i> 
struct nice_type; 

template<class T> 
struct is_nice : std::false_type {}; 

template<int i> 
struct is_nice< nice_type<i> > : std::integral_constant<int, i> {}; 

template<class T, class = void> 
struct pick 
{ 
    typedef std::integral_constant<int, -1> type; 
}; 

template<class T> 
struct pick<T, typename std::enable_if< is_nice<T>::value >::type > 
{ 
    typedef std::integral_constant<int, is_nice<T>::value > type; 
}; 

int main() 
{ 
    std::cout << pick<int>::type::value << ", "; 
    std::cout << pick< nice_type<42> >::type::value << std::endl; 
    return 0; 
} 

बजना (3.4.1) आउटपुट "-1, -1", जबकि जीसीसी (4.9.0) आउटपुट "-1, 42"।

समस्या pick की विशेषज्ञता में बताती है। जबकि जीसीसी is_nice<T>::value (42) से bool(true) को परिवर्तित करने में प्रसन्न है, क्लैंग ऐसा नहीं करता है, और विशेषज्ञता को त्याग देता है। दोनों उदाहरण -std=c++11 के साथ संकलित किए गए हैं।

कौन सा संकलक सही है?

+1

का मूल्यांकन आपका मतलब है 'लाइन 8 में' cool_type' के बजाय nice_type' करें? –

+0

@RSahu हाँ, क्षमा करें। – sbabbi

+0

इसके लिए क्या है? –

उत्तर

9

यह जीसीसी बग 57891 है। अभिन्न स्थिरांक 42 से bool का रूपांतरण एक संकीर्ण रूपांतरण शामिल है, जिसे गैर-प्रकार के टेम्पलेट तर्कों में अनुमति नहीं है। इसलिए enable_if खराब गठित है, और pick विशेषज्ञता को त्याग दिया जाना चाहिए, क्योंकि क्लैंग सही तरीके से करता है।

§14.3.2/5 [temp.arg.nontype]

The following conversions are performed on each expression used as a non-type template-argument. If a non-type template-argument cannot be converted to the type of the corresponding template-parameter then the program is ill-formed.
— For a non-type template-parameter of integral or enumeration type, conversions permitted in a converted constant expression (5.19) are applied.
...

§5.19/3 [expr.const]

... A converted constant expression of type T is an expression, implicitly converted to a prvalue of type T , where the converted expression is a core constant expression and the implicit conversion sequence contains only user-defined conversions, lvalue-to-rvalue conversions (4.1), integral promotions (4.5), and integral conversions (4.7) other than narrowing conversions (8.5.4).

§8.5.4/7 [dcl.init.list]

A narrowing conversion is an implicit conversion
...
— from an integer type or unscoped enumeration type to an integer type that cannot represent all the values of the original type, except where the source is a constant expression whose value after integral promotions will fit into the target type.

01 अपने विशेष को

error: non-type template argument evaluates to 10, which cannot be narrowed to type 'bool' [-Wc++11-narrowing]

foo<10> f; 
    ^

ठीक:

template<bool> 
struct foo{}; 
foo<10> f; 

int main() {} 

जीसीसी-4.9 जबकि बजना-3.4 यह निम्न त्रुटि के साथ खारिज कर दिया कोड स्वीकार करता है:

यह minimal example जीसीसी बग को दर्शाता है समस्या आसान है। सुनिश्चित करें कि enable_if करने के लिए गैर प्रकार टेम्पलेट तर्क एक bool

template<class T> 
struct pick<T, typename std::enable_if< is_nice<T>::value != 0 >::type > 
//              ^^^^^^ 
{ 
    typedef std::integral_constant<int, is_nice<T>::value > type; 
}; 
संबंधित मुद्दे