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,
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.
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;
}
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.
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
I suggest to take a look at the Eigen library static assert mechanism:
http://eigen.tuxfamily.org/dox/StaticAssert_8h_source.html
See static_assert (C++0x only); if on an older version, see Boost's StaticAssert.