2013-08-27 7 views
5

मुझे लगता है कि जीसीसी 4.8 के साथ ठीक संकलित करने के लिए लगता है बजना 3.3 के साथ कुछ कोड संकलन कर रहा हूँ:बजना 3.3 और constexpr बाधाओं

मूल कोड था:

template <std::size_t N> struct helper { typedef void type; }; 
template <> struct helper<64> { typedef int64_t type; }; 
template <> struct helper<32> { typedef int32_t type; }; 
template <> struct helper<16> { typedef int16_t type; }; 
template <> struct helper<8> { typedef int8_t type; }; 

template <std::size_t I, std::size_t F> 
struct test 
{ 
    typedef typename helper<I+F>::type value_type; 
    static constexpr std::size_t frac_mask = ~((~value_type(0)) << F); 
}; 

बजना में, यदि मैं घोषणा करने का प्रयास परीक्षण < 16,16> या परीक्षण < 8.0> मैं त्रुटि मिलती है:

test.cpp:41:34: error: constexpr variable 'frac_mask' must be initialized by a constant expression

static constexpr std::size_t frac_mask = ~((~value_type(0)) << F); 

इसके साथ चारों ओर खेलने, अगर मैं करने के लिए कोड में परिवर्तित:

है वहाँ कुछ नियम -

test.cpp:23:36: error: constexpr variable 'frac_mask' must be initialized by a constant expression

test.cpp:66:15: note: in instantiation of template class 'test<8, 0>' requested here

test.cpp:23:66: note: left shift of negative value -1

static constexpr mask_type frac_mask = ~((~mask_type(0)) << F); 

मेरा प्रश्न है:

template <std::size_t I, std::size_t F> 
struct test 
{ 
    typedef typename helper<I+F>::type value_type; 
    typedef typename std::make_unsigned<value_type>::type mask_type; 

    static constexpr mask_type frac_mask = ~((~mask_type(0)) << F); 
}; 

यह ज्यादातर मामलों में संकलित (मैं, एफ के मूल्यों), लेकिन अगर मैं परीक्षण < 8, 0> घोषित, मैं त्रुटि मिलती है मैं यहाँ constexpr के विनिर्देश के संदर्भ में उल्लंघन कर रहा हूँ? साथ ही, आखिरी त्रुटि के लिए - मास्क प्रकार हस्ताक्षरित है - क्या यह एक कंपाइलर मुद्दा है जो मुझे लगता है कि मैं नकारात्मक मान स्थानांतरित कर रहा हूं या क्या मैं कोड को गलत तरीके से पढ़ रहा हूं?

+0

[डिफ़ॉल्ट टेम्पलेट तर्क में constexpr कॉलिंग] के संभावित डुप्लिकेट (http://stackoverflow.com/questions/10721130/calling-constexpr-in-default-template-argument) –

+0

प्रकार पदोन्नति नियमों अपने uint8_t परिवर्तित करने के लिए int, जो हस्ताक्षरित है? –

उत्तर

3

पहले मामले में, आप हस्ताक्षरित ओवरफ्लो का कारण बन रहे हैं। एक अभिव्यक्ति नहीं के लिए शर्तों में से एक, एक निरंतर अभिव्यक्ति, सी ++ 11 5.19/2 में सूचीबद्ध होने के लिए है कि यह

a result that is not mathematically defined or not in the range of representable values for its type

शामिल है एक अहस्ताक्षरित प्रकार है, जो मॉड्यूलर अंकगणितीय उपयोग करने के लिए परिभाषित किया गया है का उपयोग करके , परिणाम सीमा में बनी हुई है। संभवतः, क्लैंग की तुलना में जीसीसी इस नियम के बारे में कम सख्त है।

अंतिम मामले में, हस्ताक्षरित 8-बिट प्रकार को int पर प्रचारित किया गया है, एक हस्ताक्षरित प्रकार नहीं है, इसलिए आपको फिर से ओवरफ़्लो हस्ताक्षरित हो जाता है। आप शायद ठीक कर सकते हैं कि negating के बाद अहस्ताक्षरित प्रकार पर वापस परिवर्तित करके:

static constexpr mask_type frac_mask = ~(mask_type(~mask_type(0)) << F); 

हालांकि मैं उस के बारे में काफी यकीन नहीं है, और साथ परीक्षण करने के लिए एक बजना स्थापना की जरूरत नहीं है।

+0

ऐसा लगता है कि यह ठीक करने के लिए प्रतीत होता है - क्या आप मुझे समझा सकते हैं कि एक हस्ताक्षरित प्रकार की बिटवाई नहीं क्यों int को बढ़ावा दिया जाएगा? – user2721897

+0

@ user2721897: पदोन्नति नियम निर्दिष्ट करते हैं कि इसे 'int' में पदोन्नत किया गया है यदि वह मूल प्रकार के सभी मानों का प्रतिनिधित्व कर सकता है; जो किसी भी छोटे प्रकार, हस्ताक्षरित या हस्ताक्षरित के लिए मामला है। –

+0

@ user2721897 हस्ताक्षर किए गए चार को * * (या कोई अंकगणितीय ऑपरेटर) लागू करने के लिए int * को बढ़ावा दिया जाता है। इसका मतलब है कि उदा। 'intvar greggo

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