views:

170

answers:

2

While reviewing Visual C++ codebase I found a following strange thing. A run-time assert (which is check the condition and throw an exception if the condition is violated) was used in a case when the condition could be evaluated at compile time:

assert( sizeof( SomeType ) == sizeof( SomeOtherType ) );

clearly the compiler will evaluate the condition and replace the code that will effectively be either

assert( true );

which does nothing or

assert( false );

which throws an exception every time control passes through that line.

IMO a compile-time assert should have be used instead for the following reasons:

  • it would expose the condition violation earlier - at compile time - and
  • it would let cleaner (thus faster and smaller) machine code be emitted

Looks like a compile-time assert is the only right thing. Is there any possible reason to prefer a run-time assert here?

+13  A: 

There's no reason to prefer a run-time assert here. You should prefer compile-time errors over run-time errors so there's never a reason, given the option between the two, to choose a run-time assert.

However, if a static assert isn't an option (doesn't know the concept of a static assert, doesn't know how to make one and doesn't have one available, or knows how to make one but doesn't have the time to), a run-time assert is the next best thing.

With C++0x, the built-in static_assert feature should end all reason to use a run-time assert where a compile-time assert would work.

GMan
+2  A: 

We can't tell without context. In template code, some branches might be unreachable for some instantiations. A compile-time assert would be inappropriate, as that renders the entire function illformed. An assert(<type-dependent expression>) does not.

E.g.

template <typename T> void foo(T t)
{
  if (t < 0) {
    assert(std::numeric_limits<T>::min() < 0);
    T u = t - std::numeric_limits<T>::min();
  }
}

The assert cannot be converted to a static assert, even though the run-time assert never fails.

MSalters
Why can't it be made a `static_assert`?
GMan
`assert(std::numeric_limits<T>::min < 0);` always fails, regardless of T.
usta
@usta: are you commenting on the lack of a function call? @MSalters: I think you wanted `min()`
Dennis Zickefoose
@Dennis Zickefoose Yes, I'm commenting on absence of (). With it added, that assert still can't be turned into static assert because std::numeric_limits<T>::min() is not (yet) a compile-time expression.
usta
Fixed missing (). @Gman: because a `static_assert` would stop `foo<unsigned int>` from compiling.
MSalters