0

I have tried to use this suggestion to do a static assert, but I do not get a compilation error if I use it within a method of a template.

The example follows :

#include <iostream>

#define STATIC_ASSERT(expr, msg)               \
{                                              \
    char STATIC_ASSERTION__##msg[(expr)?1:-1]; \
    (void)STATIC_ASSERTION__##msg[0];          \
}

template <typename T >
class A
{
public:
  int foo(const int k )
  {
    // does not work
    STATIC_ASSERT( k > 9, error_msg );
    return k+5;
  }
};

int bar(const int k )
{
  // works fine
  //STATIC_ASSERT( k > 9, error_msg );
  return k+5;
}

int main()
{
  A<int> a;
  const int v = 2;

  std::cout<<a.foo(v)<<std::endl;
  std::cout<<bar(v)<<std::endl;

  // works fine
  //STATIC_ASSERT( v > 9, error_msg );
}

I compiled it with g++ 4.7.2, with a warning that VLAs are not supported by c++ ISO :

g++ -Wall -g  -std=c++98 -Wextra -pedantic gvh.cpp

So, why the compilation doesn't fail when the STATIC_ASSERT is used within the template method? Is there a way to make it fail?

NOTE : I need a c++98 (maybe even c++03) solution, if possible only with macros.

Community
  • 1
  • 1
BЈовић
  • 62,405
  • 41
  • 173
  • 273
  • 1
    Boost has a pre-C++11 static assert. – chris Jan 31 '13 at 09:09
  • @chris Yes, I am aware of BOOST_STATIC_ASSERT, but it uses SFINAE to do a check. – BЈовић Jan 31 '13 at 09:12
  • 1
    In the answers and above there's good advice on which static assert mechanisms are around, but more fundamentally in your specific usage you're trying to assert on a function parameter - just because it's `const int` doesn't mean it's compile-time constant - that just means the function takes a copy of the runtime argument and won't allow the called code to modify it. You'll need to accept `k` as a template parameter (either for `A` or by making `A::foo` a `template `, or maybe fiddle with C++11 `constexpr`, to get the compile time check you're expecting. – Tony Delroy Jan 31 '13 at 09:33

5 Answers5

13

Prior to C++11 I would normally do:

typedef int static_assert_something[something ? 1 : -1];

You can also look at boost static assert. But it is too bloated for my liking. It is easy to make things bigger, it is hard to make them any better.

Maxim Egorushkin
  • 131,725
  • 17
  • 180
  • 271
  • 1
    Just for clarity(I always hated the typedef syntax): this works by trying to make a typedef to an array of size 1 or -1 depending on the truth value? – Tim Seguine Apr 27 '18 at 13:15
  • @TimSeguine Correct. – Maxim Egorushkin Apr 30 '18 at 15:41
  • Careful, this will invoke undefined behavior if `something` is not a compile-time constant and the compiler supports variable-length arrays. See https://stackoverflow.com/a/3783369/2192139 – Geier Jul 15 '22 at 13:03
  • @Geier I would like to see an example. – Maxim Egorushkin Jul 15 '22 at 15:48
  • @MaximEgorushkin https://godbolt.org/z/ba59qz6PK No compile error on gcc or clang. If the (not-static) assertion is violated, the program returns `sizeof(...) = -4`. – Geier Jul 16 '22 at 16:34
3

Consider something like Boost.StaticAssert, although if that is unavailable to you you can try defining a template.

template<bool>
struct static_assertion;

template<>
struct static_assertion<true> {};

Though that has the drawback of not having a message associated to it.

After a bit of searching through StackOverflow, I stumbled upon this question which had a similar answer to mine and a bunch of alternatives for doing it without boost.

Community
  • 1
  • 1
Rapptz
  • 20,807
  • 5
  • 72
  • 86
3

This is basically Maxim's answer with a little more convenient interface. I have taken it from here. Nice thing about it is that the use of templates prevents the user from passing a non-compile-time-constant value as the condition.

template<bool Is_Condition_Met>
struct Static_assert_cpp98
{
  static void apply() {static const char junk[ Is_Condition_Met ? 1 : -1 ];}
};

template<>
struct Static_assert_cpp98<true>
{
  static void apply() {}
};

#define STATIC_ASSERT_CPP98(condition) Static_assert_cpp98<condition>::apply()
Hashimoto
  • 306
  • 4
  • 8
1

If you add call to the method in question (a.foo();), the static assert will fail (just then the method will be compiled). You do know that you should not static assert on run time values like "k" I presume.

1
int foo(const int k)
{
  STATIC_ASSERT( k > 9, error_msg );
  return k+5;
}

Static assertions only work with compile-time constant expressions.

k is not a compile-time constant expression.

Non-type template parameters are compile-time constant expressions during template instantiation, so you could adapt your code thus:

template <int K>
int foo()
{
  STATIC_ASSERT( K > 9, error_msg );
  return K+5;
}
Oktalist
  • 14,336
  • 3
  • 43
  • 63