2016-04-05 10 views
6

जीसीसी (5.3) & क्लैंग (3.8) दावा करते हैं कि test में पहली पंक्ति खराब है, लेकिन दूसरा ठीक है। एमएसवीसी (2015.2) कहता है, दोनों अमान्य हैं।constexpr टेम्पलेट तर्क अजीबता

template< typename N, typename T > 
void f(N n, T t) { std::get<n>(t); } 
void test() { 
    std::get< std::integral_constant< size_t, 0 >() >(std::make_tuple(123)); // not ok 
    f(std::integral_constant< size_t, 0 >(), std::make_tuple(123)); // ok for gcc, clang, but not msvc 
} 

मानक के अनुसार, वास्तव में क्या अंतर है? क्या यह कोड शुरू करने के लिए कानूनी है? पहली पंक्ति के लिए


बजना त्रुटि:

In file included from main.cpp:2: 
/usr/local/bin/../lib/gcc/x86_64-unknown-linux-gnu/5.3.0/../../../../include/c++/5.3.0/tuple:874:34: error: no matching function for call to '__get_helper2' 
    { return std::forward<_Tp&&>(std::__get_helper2<_Tp>(__t)); } 
           ^~~~~~~~~~~~~~~~~~~~~~~ 
main.cpp:10:10: note: in instantiation of function template specialization 'std::get<std::integral_constant<unsigned long, 0>(), int>' requested here 
    std::get<std::integral_constant<size_t, 0>()>(std::make_tuple(123)); // not ok 
     ^
/usr/local/bin/../lib/gcc/x86_64-unknown-linux-gnu/5.3.0/../../../../include/c++/5.3.0/tuple:856:5: note: candidate template ignored: could not match '_Tuple_impl' against 'tuple' 
    __get_helper2(_Tuple_impl<__i, _Head, _Tail...>& __t) noexcept 
    ^
/usr/local/bin/../lib/gcc/x86_64-unknown-linux-gnu/5.3.0/../../../../include/c++/5.3.0/tuple:861:5: note: candidate template ignored: could not match '_Tuple_impl' against 'tuple' 
    __get_helper2(const _Tuple_impl<__i, _Head, _Tail...>& __t) noexcept 
    ^
1 error generated. 

जीसीसी त्रुटि:

In file included from main.cpp:2:0: 
/usr/local/include/c++/5.3.0/tuple: In instantiation of 'constexpr _Tp&& std::get(std::tuple<_Elements ...>&&) [with _Tp = std::integral_constant<long unsigned int, 0ul>(); _Types = {int}]': 
main.cpp:10:75: required from here 
/usr/local/include/c++/5.3.0/tuple:874:57: error: no matching function for call to '__get_helper2(std::tuple<int>&)' 
    { return std::forward<_Tp&&>(std::__get_helper2<_Tp>(__t)); } 
                 ^
/usr/local/include/c++/5.3.0/tuple:856:5: note: candidate: template<class _Head, long unsigned int __i, class ... _Tail> constexpr _Head& std::__get_helper2(std::_Tuple_impl<__i, _Head, _Tail ...>&) 
    __get_helper2(_Tuple_impl<__i, _Head, _Tail...>& __t) noexcept 
    ^
/usr/local/include/c++/5.3.0/tuple:856:5: note: template argument deduction/substitution failed: 
/usr/local/include/c++/5.3.0/tuple:874:57: note: mismatched types 'std::integral_constant<long unsigned int, 0ul>()' and 'int' 
    { return std::forward<_Tp&&>(std::__get_helper2<_Tp>(__t)); } 
                 ^
/usr/local/include/c++/5.3.0/tuple:874:57: note: 'std::tuple<int>' is not derived from 'std::_Tuple_impl<__i, std::integral_constant<long unsigned int, 0ul>(), _Tail ...>' 
/usr/local/include/c++/5.3.0/tuple:861:5: note: candidate: template<class _Head, long unsigned int __i, class ... _Tail> constexpr const _Head& std::__get_helper2(const std::_Tuple_impl<__i, _Head, _Tail ...>&) 
    __get_helper2(const _Tuple_impl<__i, _Head, _Tail...>& __t) noexcept 
    ^
/usr/local/include/c++/5.3.0/tuple:861:5: note: template argument deduction/substitution failed: 
/usr/local/include/c++/5.3.0/tuple:874:57: note: mismatched types 'std::integral_constant<long unsigned int, 0ul>()' and 'int' 
    { return std::forward<_Tp&&>(std::__get_helper2<_Tp>(__t)); } 
                 ^
/usr/local/include/c++/5.3.0/tuple:874:57: note: 'std::tuple<int>' is not derived from 'const std::_Tuple_impl<__i, std::integral_constant<long unsigned int, 0ul>(), _Tail ...>' 
+0

क्या आप कृपया हमें बता सकते हैं कि आपको कौन सी त्रुटियां मिलती हैं? –

+0

मैं यहाँ टेक्स्ट की दीवारों को पोस्ट करने में बहुत सहज नहीं हूं, लेकिन यहां इसकी जानकारी है। एमएसवीसी के तहत दूसरी पंक्ति: "'std :: get': कोई मिलान ओवरलोडेड फ़ंक्शन नहीं मिला"। पहली पंक्ति: समान प्रकार के साथ सामान्य मम्बो-जंबो के सभी प्रकार 'std :: tuple' के आंतरिक संकेतों को इंगित करते हैं। – vpozdyayev

+1

@vpozdyayev त्रुटियां बहुत मदद करती हैं - यह त्रुटि संदेश है जिसने मुझे यह समझने के लिए प्रेरित किया कि समस्या क्या थी। यह सिर्फ मम्बो-जंबो नहीं है। – Barry

उत्तर

6

tl; डॉ मुझे लगता है कि दोनों ही मामलों में जीसीसी और बजना के व्यवहार सही है।


आपके दो कॉल के बीच एक सूक्ष्म अंतर है। मुझे सिर्फ वर्णन करने के लिए एक अन्य नाम जोड़ें:

using Zero = std::integral_constant<size_t, 0>; 
auto tuple = std::make_tuple(123); 

जब आप लिखें:

std::get<Zero()>(tuple); 

Zero() एक प्रकार है। यह Zero लौटने वाला एक नलिका फ़ंक्शन है। इस प्रकार, आप std::get के संस्करण को कॉल कर रहे हैं जो एक प्रकार लेता है: std::get<T>()। चूंकि tuple में कोई तत्व नहीं है, जिस प्रकार Zero() है, यह एक त्रुटि है।

दूसरी ओर, जब आप लिखते हैं:

Zero n; 
std::get<n>(tuple); 

n एक प्रकार नहीं है - यह केवल कभी एक मूल्य है। चूंकि std::integral_constant में constexpr operator size_t() है, जिसका उपयोग किया जाता है और आप std::get<I>() पर कॉल करना समाप्त करते हैं, जो आप अपेक्षा करते हैं।

एक ही बस के रूप में अच्छी ब्रेस आरंभीकरण का उपयोग करके पूरा किया जा सकता है:

std::get<Zero{}>(tuple); 

Zero{} के बाद निश्चित रूप से एक प्रकार नहीं है।

+1

आह, अच्छा ओल 'सबसे परेशान पार्स :) ... सी ++ हाल के वर्षों में इतना सुविधाजनक हो रहा है कि मैं पूरी तरह से भूल गया था। – vpozdyayev

+0

दरअसल ... 'std :: (tuple) प्राप्त करें;' लाइन केवल क्लैंग में काम करती है, लेकिन जीसीसी नहीं ("एन 'का मान निरंतर अभिव्यक्ति में उपयोग करने योग्य नहीं है"/"' n 'घोषित नहीं किया गया था 'constexpr' ")। क्या यह एक जीसीसी बग होगा? – vpozdyayev

+0

@vpozdyayev यह आपके कामकाजी मामले का एक संक्षिप्त संस्करण होना था, वास्तव में मान्य कोड नहीं। – Barry

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