Compile-time assertion?

后端 未结 12 983
春和景丽
春和景丽 2020-11-27 06:09

Is there a way I can assert that two constant expressions are equal at compile time?

e.g. I want this to cause a compile-time error

enum { foo=263,          


        
相关标签:
12条回答
  • 2020-11-27 06:22

    Similar to iammillind's solution, which was unfortunately one only useful at runtime:

    template <int A, int B>
    class VALUES { 
    };
    
    // specialization to provide safe passage for equal values        
    template <int X>
    class VALUES<X, X> {
    public:
       static void MY_VALUES_ARE_EQUAL() {}
    };
    
    
    #define ASSERT_EQUALITY(a, b)    \
    {    \
       typedef VALUES<a, b> COMPILE_TIME_ASSERTION;       \
       COMPILE_TIME_ASSERTION::VALUES_ARE_EQUAL();     \
    }
    
    int main() {
       ASSERT_EQUALITY(1, 1);    // compiles just fine
       ASSERT_EQUALITY(1, 2);    // ERROR!
       // . . . 
     }
    

    The nice thing about this is that it provides a nice compiler message. My compiler tells me the following:

    ‘VALUES_ARE_EQUAL’ is not a member of ‘COMPILE_TIME_ASSERTION {aka VALUES<1, 2>}’

    You don't need the typedef. Without:

    'VALUES_ARE_EQUAL' is not a member of 'VALUES<1, 2>'

    Of course, there are a bunch of other ways to generate helpful messages. For giggles:

    // these give use some tips in the compiler warnings
    class COMPILE_TIME_EQUALITY_ASSERTION {} compiler_message; 
    class EQUAL_VALUES_ONLY_PLEASE {};
    
    
    template <int A, int B>
    class VALUES {
    public:
       static void AreEqual(EQUAL_VALUES_ONLY_PLEASE) {}
    };
    
    template <int X>
    class VALUES<X, X>
    {
    public:
       static void AreEqual(COMPILE_TIME_EQUALITY_ASSERTION) {}
    };
    
    
    #define ASSERT_EQUALITY(a, b)                                   \
    {                                                               \
       VALUES<a, b>::AreEqual(compiler_message);                             \
    }
    
    int main() {
        ASSERT_EQUALITY(1, 1) // a-okay
        ASSERT_EQUALITY(1, 2) // ERROR!
    }
    

    I get the following compiler errors:

    no matching function for call to:
    ‘VALUES<1,2>::AreEqual(COMPILE_TIME_EQUALITY_ASSERTION&)' 
    candidate is:
    static void VALUES<\A, B>::AreEqual(EQUAL_VALUES_ONLY_PLEASE) [with int A = 1, int B = 2]
    

    combinations of static member functions/constructors/field assignment/privacy and template specifications can yield different results perhaps more appropriate for your situation.

    0 讨论(0)
  • 2020-11-27 06:25

    you can define your own static assertion , this way :

    #include <iostream>
    template <bool b> class ClassStaticAssert;
    template <>
    class ClassStaticAssert<true>{static const bool value = true;};
    #define STATIC_ASSERT(e) (ClassStaticAssert<e>())
    int main()
    {
        STATIC_ASSERT(0);
        return 0;
    }
    
    0 讨论(0)
  • 2020-11-27 06:31

    Yes. You can do this with template specializations on type bool, like this:

    // empty default template
    template <bool b>
    struct StaticAssert {};
    
    // template specialized on true
    template <>
    struct StaticAssert<true>
    {
        static void assert() {}
    };
    
    int f()
    {
        StaticAssert<1==1>::assert();   // compiles fine, assert() member found
        StaticAssert<1==2>::assert();   // compile failure, no assert() member for StaticAssert<false>
    }
    

    Code is basically from memory, may need some tweaks.

    0 讨论(0)
  • 2020-11-27 06:36

    For another version of a static assert, that you can glorify by adding a better name, you can use:

    // name must be a valid identifier
    #define STATIC_ASSERT( condition, name )\
        typedef char assert_failed_ ## name [ (condition) ? 1 : -1 ];
    

    And use as:

    STATIC_ASSERT( x == y, constants_must_be_same );
    

    The compiler will trigger an error similar to:

    size of array 'assert_failed_constants_must_be_same' is negative
    

    Which does not seem that helpful, but it will point to the exact line of the assert, and after a while you will start processing that error message as static assert failed

    0 讨论(0)
  • 2020-11-27 06:37

    I suggest to take a look at the Eigen library static assert mechanism:

    http://eigen.tuxfamily.org/dox/StaticAssert_8h_source.html

    0 讨论(0)
  • 2020-11-27 06:39

    See static_assert (C++0x only); if on an older version, see Boost's StaticAssert.

    0 讨论(0)
提交回复
热议问题