简体   繁体   中英

How to do static_assert with macros?

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.

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.

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.

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()

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.

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;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM