2

I am currently playing with static_assert and came across this problem:

class A
{
public:
   void func( const int a ){
      static_assert( a == 3 );
   }
};

Gives me:

error: non-constant condition for static assertion static_assert( a == 3 );

Why is this? My a is const. I could imagine that the value will be cast to const and was previously non const, then yes an error should appear. But only inside the member function, I wouldn't expect any errors.

How can I solve that? If not solveable I am also glad about an answer, kinda curious here.

Dimfred
  • 182
  • 2
  • 16

3 Answers3

7

The expression in a static_assert must be a compile-time constant. A const function parameter is merely immutable, but not known at compile time.

Sebastian Redl
  • 69,373
  • 8
  • 123
  • 157
4

Why is this? My a is const.

Because your a is not compile time const. The error message is not very precise in this regard. The expression of static_assert must be compile time constant.

const usually declares runtime constness. It ensures that the object won't be modified throughout its lifetime. But the compiler cannot know what value would be used to initialise the argument (i.e. passed to the function) at runtime.

How can I solve that?

Either don't use static_assert, or use a template argument instead of runtime argument (in which case you need to have a function template in the first place). Example:

template<int a>
void func(){
   static_assert(a == 3);
}
eerorika
  • 232,697
  • 12
  • 197
  • 326
1

Interestingly, top-level const (and volatile) qualifiers on function parameters are ignored. Try it - you can't have an overload set like

void func(int a);
void func(const int a);

This is roughly because the top-level type (ie, not the pointed-to-type if the argument is a pointer) is already passed by value, in some sense. (This intuitive argument doesn't exactly work for references, but they're always immutable anyway).

Anyway, even if it really were const (which it definitely isn't), that's just a promise not to mutate an otherwise runtime-mutable value. It doesn't make it known at compile time.

Consider that this would compile, and even if the argument were const int &, that's only a promise that func won't mutate i. No-one knows the value until the program is run and receives input.

int i;
std::cin >> i;
a.func(i);

You could instead write

template <int a>
void func(){
  static_assert( a == 3 );
}
Useless
  • 64,155
  • 6
  • 88
  • 132
  • What is even more fun is you can declare the function as `void func(int a);` and then define it as `void func(const int a) { code }` so you have const correctness in the function. http://coliru.stacked-crooked.com/a/0ce28725d0c1f2c2 – NathanOliver Sep 03 '19 at 14:12