2010-05-25 21 views
5

स्थिर आवेषण संकलन समय में चीजों की जांच के लिए बहुत सुविधाजनक हैं। एक साधारण स्थिर ज़ोर मुहावरा इस तरह दिखता है:कॉन्स चर के लिए स्थैतिक जोर?

template<bool> struct StaticAssert; 
template<> struct StaticAssert<true> {}; 

#define STATIC_ASSERT(condition) do { StaticAssert<(condition)>(); } while(0) 

यह

STATIC_ASSERT(sizeof(float) == 4) 

की तरह सामान के लिए अच्छा है और:

#define THIS_LIMIT (1000) 
... 
STATIC_ASSERT(THIS_LIMIT > OTHER_LIMIT); 

लेकिन #define का उपयोग कर परिभाषित करने का "सी ++" तरीका नहीं है स्थिरांक।

namespace { 
    const int THIS_LIMIT = 1000; 
} 

या यहाँ तक कि: सी ++ आप एक गुमनाम नाम स्थान का उपयोग करना होगा

static const int THIS_LIMIT = 1000; 

इस के साथ परेशानी यह है कि एक const int साथ आप STATIC_ASSERT() उपयोग नहीं कर सकते हैं और आप एक रन-टाइम का सहारा चाहिए जांचें कि मूर्ख क्या है।

क्या मौजूदा सी ++ में इसे ठीक से हल करने का कोई तरीका है?
मुझे लगता है कि मैं पढ़ा है C++ 0x यह करने के लिए कुछ की सुविधा है ...


संपादित

ठीक है तो यह

static const int THIS_LIMIT = 1000; 
... 
STATIC_ASSERT(THIS_LIMIT > 0); 

ठीक संकलित
लेकिन यह:

static const float THIS_LIMIT = 1000.0f; 
... 
STATIC_ASSERT(THIS_LIMIT > 0.0f); 

नहीं करता है।
(विजुअल स्टूडियो 2008 में)

कैसे आते हैं?

+0

आप BOOST_STATIC_ASSERT के बजाय एनआईएच स्थिर आवेषण का उपयोग क्यों कर रहे हैं? http://www.boost.org/doc/libs/1_43_0/doc/html/boost_staticassert।एचटीएमएल –

+0

मैं कुछ मूर्ख कॉर्पोरेट कारण – shoosh

+1

के लिए बूस्ट (अभी तक) का उपयोग नहीं कर सकता क्या आपको लगता है कि आप इस मामले में अभिन्न स्थिरांक का उपयोग नहीं कर सकते हैं? उपर्युक्त बस ठीक काम करना चाहिए। –

उत्तर

10

क्यों, आप कर सकते हैं अभी भी स्थिरांक पूर्णांक के साथ स्थिर ज़ोर:

#define static_assert(e) extern char (*ct_assert(void)) [sizeof(char[1 - 2*!(e)])] 
static_assert(THIS_LIMIT > OTHER_LIMIT) 

इसके अलावा, use boost!

BOOST_STATIC_ASSERT(THIS_LIMIT > OTHER_LIMIT) 

... आप एक बहुत अच्छे त्रुटि संदेश मिल जाएगा ...

+0

ठीक है, मेरे लिए एक सबक है। यह कहने से पहले कुछ भी संभव नहीं है ... – shoosh

+0

मुझे अभी भी आश्चर्य है कि किस समस्या को ठीक करना है? –

+0

@Shoosh: आप मूल कोड को संकलित करना चाहिए। [मेरा जवाब] देखें (http://stackoverflow.com/questions/2902917/2903013#2903013)। – sbi

1

शायद आप सी, जहां const int एक सच्चे संकलन समय निरंतर का प्रतिनिधित्व नहीं करता साथ सी ++ के व्यवहार भ्रमित कर रहे हैं। या शायद आपका सी ++ संकलक टूट गया है। यदि यह वास्तव में उत्तरार्द्ध है, तो इसके बजाय enum का उपयोग करें।

+0

आपको +1 मिला, मुझे एक ही समाधान के लिए -1 मिला =/ –

+0

@ विकटर सेहर: निष्पक्ष होने के लिए, मेरा उत्तर आपके मुकाबले मोर स्पष्टीकरण प्रदान करता है, और इस मामले के लिए 'enum' * * आवश्यक नहीं होना चाहिए। – jamesdlin

+0

@ विकटररहर: यह जगह कोड के स्निपेट में "समाधान" को चकित करने के बारे में नहीं है जैसे कि वे मांस के टुकड़े थे; यह व्याख्या करने, सिखाने और सूचित करने के लिए _answers_ लिखने के बारे में है। अक्सर, अच्छे उत्तरों में कोड चित्रण शामिल होते हैं, लेकिन यह _not_ का अर्थ नहीं है कि एक उत्तर जिसमें कोड का _solely_ होता है वह एक अच्छा है। वास्तव में, यह दुर्लभ है कि यह मामला है। –

1

यह:

namespace { 
    const int THIS_LIMIT = 1000; 
} 

template<bool> struct StaticAssert; 
template<> struct StaticAssert<true> {}; 

#define STATIC_ASSERT(condition) do { StaticAssert<(condition)>(); } while(0) 

int main() 
{ 
    STATIC_ASSERT(THIS_LIMIT > 5); 

    return (0); 
} 

कुलपति और Comeau के साथ ठीक संकलित करता है।

0

enum{THIS_LIMIT = 1000};

+0

क्यों -1 वोट? –

+1

मैंने आपको कम नहीं किया, लेकिन यह शायद ही दिए गए प्रश्न का उत्तर है। यह एक वैध कार्यवाही है, और यह वैध कोड है, लेकिन आपने शून्य विवरण, शून्य स्पष्टीकरण और शून्य विश्लेषण (ए) प्रदान किया है, (बी) यह ओपी के कोड से अलग कैसे है और (सी) इसका उपयोग क्यों किया जाना चाहिए (और) वास्तव में, यह _doesn't_ होने की आवश्यकता नहीं है)। नतीजतन यह थोड़ा आलसी के रूप में आता है, और शायद यही कारण है कि यह downvoted था। असल में, इसके बारे में सोचने के लिए आओ, मैं भी इसी कारण से इसे कम करने जा रहा हूं। माफ़ कीजिये। –

+0

चिंता न करें, मुझे लगता है कि आपने काफी अच्छी व्याख्या प्रदान की है :) –

4

static_assert तो जब तक आप एक अपेक्षाकृत अप-टू-डेट संकलक आप उपयोग कर सकते हैं मिल गया है के रूप में C++ 0x में एक संकलक विशेषता है।#define static_assert(x) ... करने के लिए देखें, क्योंकि यह C++ 0x में एक वास्तविक कीवर्ड है, इसलिए आप कंपाइलर सुविधा को स्थायी रूप से छुपाएंगे। इसके अलावा, C++ 0x static_assert ताकि आप अपने आप भविष्य में स्विच करने के लिए करता है, तो आपको लगता है कि #define का उपयोग कोशिश कर समस्याएं पैदा कर सकता, दो पैरामीटर (जैसे। static_assert(sizeof(int) == 4, "Expecting int to be 4 bytes")) लेता है।

2

ऐसा लगता है कि आप वास्तव में पूछ क्यों निम्नलिखित मामला है (और मैं पुष्टि कर सकता है कि दोनों जीसीसी 4.3.4 और विजुअल C++ 2008 एक्सप्रेस में) कर रहे हैं कि:

template<bool> struct StaticAssert; 
template<> struct StaticAssert<true> {}; 

#define STATIC_ASSERT(condition) do { StaticAssert<(condition)>(); } while(0) 


static const int AN_INT = 1000; 
static const float A_FLOAT = 1000.0f; 

int main() 
{ 
    STATIC_ASSERT(AN_INT > 0);  // OK 
    STATIC_ASSERT(A_FLOAT > 0.0f); // Error: A_FLOAT may not appear in a constant expression 
} 

की संख्या में हैं स्थिर रूप से फ़्लोटिंग-पॉइंट मानों का उपयोग करने पर प्रतिबंध। नोट, उदाहरण के लिए, कि आप उन्हें टेम्पलेट तर्क के रूप में पास नहीं कर सकते हैं।

[C++11: 5.19/2]:एक सशर्त अभिव्यक्ति एक कोर निरंतर अभिव्यक्ति है जब तक कि यह एक संभावित का मूल्यांकन उपसूचक (3.2) के रूप में निम्न में से एक शामिल है, लेकिन तार्किक और (5.14) की subexpressions, तार्किक: क्योंकि यही कारण है या (5.15), और सशर्त (5.16) कार्य है कि मूल्यांकन नहीं किया जाता नहीं माना जाता है [नोट: एक अतिभारित ऑपरेटर एक समारोह का आह्वान। अंत टिप्पणी] :

  • [..]
  • एक lvalue करने वाली rvalue रूपांतरण (4.1), जब तक यह
    • का अभिन्न अंग या गणन के glvalue लागू किया जाता है टाइप कि एक पूर्ववर्ती आरंभीकरण के साथ एक नॉन-वोलाटाइल स्थिरांक वस्तु, एक निरंतर अभिव्यक्ति के साथ प्रारंभ करने के लिए संदर्भित करता है, या
    • शाब्दिक प्रकार का एक glvalue को संदर्भित करता है एक गैर अस्थिर वस्तु constexpr के साथ परिभाषित, या कि इस तरह के एक वस्तु की एक उप-वस्तु को संदर्भित करता है, या
    • शाब्दिक प्रकार का एक glvalue कि एक गैर अस्थिर अस्थायी वस्तु जिसका जीवन समाप्त नहीं किया है को संदर्भित करता है, एक निरंतर साथ प्रारंभ अभिव्यक्ति;
  • [..]

(यानी केवल अभिन्न और गणन प्रकार की अनुमति है;। कोई फ्लोटिंग प्वाइंट प्रकार)

इस नियम के लिए कारण का सवाल है, मैं मैं पूरी तरह से सुनिश्चित नहीं हूं, लेकिन निम्नलिखित प्रकार के तर्क के साथ कुछ करने के लिए कुछ हो सकता है:

[C++11: 5.19/4]: [..] चूंकि इस अंतर्राष्ट्रीय मानक ने पर फ़्लोटिंग-पॉइंट ऑपरेशंस की सटीकता पर कोई प्रतिबंध नहीं लगाया है, यह निर्दिष्ट नहीं है कि अनुवाद के दौरान एक फ़्लोटिंग-पॉइंट अभिव्यक्ति का मूल्यांकन उसी परिणाम को उत्पन्न करता है जैसे एक ही अभिव्यक्ति के मूल्यांकन (या समान मानों पर एक ही ऑपरेशन) प्रोग्राम निष्पादन के दौरान। [..]

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