2009-12-30 9 views
22

चूंकि किसी कंपनी में बूस्ट वर्जित है, इसलिए मुझे शुद्ध सी ++ में इसकी कार्यक्षमता को लागू करने की आवश्यकता है। मैंने बढ़ावा स्रोतों में देखा है लेकिन कम से कम मेरे लिए समझने के लिए वे बहुत जटिल लगते हैं। मुझे पता है कि C++ 0x स्टैंडअर्ट में static_assert() नामक कुछ है, लेकिन मैं किसी भी C++ 0x सुविधाओं का उपयोग नहीं करना चाहता हूं।बूस्ट के बिना BOOST_STATIC_ASSERT

+0

किया

message एक वैध सी ++ पहचानकर्ता, no_you_cant_have_a_pony की तरह जो युक्त एक संकलक त्रुटि उत्पन्न करेगा हो गया है आप पूछते हैं कि आपको बूस्ट का उपयोग करने की अनुमति क्यों नहीं है? –

+3

किसी को भी मामला बनाने के लिए दर्द नहीं हुआ ताकि वकील की टीम इसके उपयोग के लिए अपनी मंजूरी दे सके? – AProgrammer

+1

@ ग्रेगरी पाकोज़, वे कहते हैं क्योंकि यह बहुत जटिल है :) – Konstantin

उत्तर

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

int main() { 
    StaticAssert< (4>3) >(); //OK 
    StaticAssert< (2+2==5) >(); //ERROR 
} 
+0

+1 काफी सरल है, लेकिन मुझे लगता है कि –

+0

@Gregory: 'StaticAssert < (2+2==5) > संबंधित संदेश(); ' –

+1

ऐसे स्थान हैं जहां आप चर नहीं चाहते हैं हालांकि –

3

आप मैक्रो को अपने कोड पर Boost source file से कॉपी कर सकते हैं। यदि आपको बूस्ट समर्थन के सभी कंपाइलरों का समर्थन करने की आवश्यकता नहीं है तो आप केवल अपने कंपाइलर के लिए सही परिभाषा चुन सकते हैं और उस फ़ाइल में शेष #ifdef s को छोड़ सकते हैं।

+2

द्वारा दावा त्रुटि को अनदेखा नहीं किया जाता है क्या यह बूस्ट के लाइसेंस के साथ कानूनी है? – gatopeich

23

एक अन्य चाल (जो सी में इस्तेमाल किया जा सकता है), तो ज़ोर असफल एक नकारात्मक आकार के साथ एक सरणी बनाने की कोशिश करने के लिए है:

#define ASSERT(cond) int foo[(cond) ? 1 : -1] 
एक बोनस के रूप

, आप एक के बजाय एक typedef का उपयोग कर सकते वस्तु, ताकि यह अधिक संदर्भों में प्रयोग करने योग्य है और नहीं है तब होता है जब यह सफल:

#define ASSERT(cond) typedef int foo[(cond) ? 1 : -1] 

अंत में, नाम टकराव की संभावना उतनी ही कम (और पुन: प्रयोज्य कम से कम में विभिन्न लाइनों) के साथ एक नाम का निर्माण:

#define CAT_(a, b) a ## b 
#define CAT(a, b) CAT_(a, b) 
#define ASSERT(cond) typedef int CAT(AsSeRt, __LINE__)[(cond) ? 1 : -1] 
+1

कोई बता सकता है कि दो सीएटी मैक्रोज़ क्यों आवश्यक हैं? आप किस समस्या से बचने की कोशिश कर रहे हैं? धन्यवाद। – grokus

+6

यदि आप ऐसा नहीं करते हैं, तो तर्क जो मैक्रोज़ हैं (जैसे '__LINE__') का विस्तार नहीं किया गया है। तो यह वांछित 'AsSeRt42' के बजाय' AsSeRt__LINE__' उत्पन्न करेगा। मुझे पूरा यकीन है कि कहीं भी विस्तार से यह एक प्रश्न है। "No_you_cant_have_a_pony" – AProgrammer

2

मैं निम्नलिखित हेडर फाइल उपयोग कर रहा हूँ, कोड के साथ किसी और से फट ...

#ifndef STATIC_ASSERT__H 
#define STATIC_ASSERT__H 

/* ripped from http://www.pixelbeat.org/programming/gcc/static_assert.html */ 

#define ASSERT_CONCAT_(a, b) a##b 
#define ASSERT_CONCAT(a, b) ASSERT_CONCAT_(a, b) 
/* These can't be used after statements in c89. */ 
#ifdef __COUNTER__ 
    /* microsoft */ 
    #define STATIC_ASSERT(e) enum { ASSERT_CONCAT(static_assert_, __COUNTER__) = 1/(!!(e)) } 
#else 
    /* This can't be used twice on the same line so ensure if using in headers 
    * that the headers are not included twice (by wrapping in #ifndef...#endif) 
    * Note it doesn't cause an issue when used on same line of separate modules 
    * compiled with gcc -combine -fwhole-program. */ 
    #define STATIC_ASSERT(e) enum { ASSERT_CONCAT(assert_line_, __LINE__) = 1/(!!(e)) } 
#endif 

/* http://msdn.microsoft.com/en-us/library/ms679289(VS.85).aspx */ 
#ifndef C_ASSERT 
#define C_ASSERT(e) STATIC_ASSERT(e) 
#endif 

#endif 
16

यहाँ मेरी कोड बेस से निकाला स्थिर दावे के अपने ही दिया गया है: Pre-C++11 Static Assertions Without Boost

उपयोग:

STATIC_ASSERT(expression, message);

जब स्थिर अभिकथन परीक्षण विफल रहता है, कि किसी तरह STATIC_ASSERTION_FAILED_AT_LINE_xxx_message शामिल एक संकलक त्रुटि संदेश उत्पन्न होता है।

STATIC_ASSERTION_FAILED_AT_LINE_1337_no_you_cant_have_a_pony :)

#define CONCATENATE(arg1, arg2) CONCATENATE1(arg1, arg2) 
#define CONCATENATE1(arg1, arg2) CONCATENATE2(arg1, arg2) 
#define CONCATENATE2(arg1, arg2) arg1##arg2 

/** 
* Usage: 
* 
* <code>STATIC_ASSERT(expression, message)</code> 
* 
* When the static assertion test fails, a compiler error message that somehow 
* contains the "STATIC_ASSERTION_FAILED_AT_LINE_xxx_message" is generated. 
* 
* /!\ message has to be a valid C++ identifier, that is to say it must not 
* contain space characters, cannot start with a digit, etc. 
* 
* STATIC_ASSERT(true, this_message_will_never_be_displayed); 
*/ 

#define STATIC_ASSERT(expression, message)\ 
    struct CONCATENATE(__static_assertion_at_line_, __LINE__)\ 
    {\ 
    implementation::StaticAssertion<static_cast<bool>((expression))> CONCATENATE(CONCATENATE(CONCATENATE(STATIC_ASSERTION_FAILED_AT_LINE_, __LINE__), _), message);\ 
    };\ 
    typedef implementation::StaticAssertionTest<sizeof(CONCATENATE(__static_assertion_at_line_, __LINE__))> CONCATENATE(__static_assertion_test_at_line_, __LINE__) 

    // note that we wrap the non existing type inside a struct to avoid warning 
    // messages about unused variables when static assertions are used at function 
    // scope 
    // the use of sizeof makes sure the assertion error is not ignored by SFINAE 

namespace implementation { 

    template <bool> 
    struct StaticAssertion; 

    template <> 
    struct StaticAssertion<true> 
    { 
    }; // StaticAssertion<true> 

    template<int i> 
    struct StaticAssertionTest 
    { 
    }; // StaticAssertionTest<int> 

} // namespace implementation 


STATIC_ASSERT(true, ok); 
STATIC_ASSERT(false, ko); 

int main() 
{ 
    return 0; 
} 
+6

+1 बहुत अच्छा! यह एक पूर्ण समाधान है (और यदि आप खुद को बढ़ावा देना चाहते हैं तो बढ़ावा देने के लिए एक अच्छा विकल्प) +1 –

+2

के लिए – Samaursa

3

मेरा मानना ​​है कि यह काम करना चाहिए:

template<bool> struct CompileTimeAssert; 
template<> struct CompileTimeAssert<true>{}; 
#define STATIC_ASSERT(e) (CompileTimeAssert <(e) != 0>()) 
संबंधित मुद्दे