Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to tell static_assert that constexpr function arguments are const?

I have a constexpr function that looks something like this:

constexpr int foo(int bar)
{
   static_assert(bar>arbitrary_number, "Use a lower number please");

   return something_const;
}

However, compiling this with GCC 4.6.3 keeps telling me

error: 'bar' cannot appear in a constant-expression

I tried something like

constexpr int foo(constexpr const int bar)
{
   static_assert(bar>arbitrary_number, "Use a lower number please");

   return something_const;
}

but constexpr can't be used for function arguments.

Is there some simple way to tell the compiler that bar is always a compile time constant?

like image 755
TravisG Avatar asked Mar 20 '12 15:03

TravisG


People also ask

Are constexpr functions const?

All constexpr variables are const . A variable can be declared with constexpr , when it has a literal type and is initialized. If the initialization is performed by a constructor, the constructor must be declared as constexpr .

Is constexpr implicitly const?

In C++11, constexpr member functions are implicitly const.

Should I use constexpr or const?

const applies for variables, and prevents them from being modified in your code. constexpr tells the compiler that this expression results in a compile time constant value, so it can be used in places like array lengths, assigning to const variables, etc.

Can a function parameter be constexpr?

We allow annotating a function parameter with constexpr with the same meaning as a variable declaration: must be initialized with a constant expression. We add a new keyword, maybe_constexpr , that deduces whether the parameter is known at compile time.


2 Answers

Is there some simple way to tell the compiler that bar is always a compile time constant?

If bar is always compile-time constant, then you should write your function as:

template<int bar>
constexpr int foo()
{
   static_assert(bar>arbitrary_number, "Use a lower number please");
   return something_const;
}

Because if you don't do so, and instead write what you've already written, then in that case, the function can be called with non-const argument as well; it is just that when you pass non-const argument, then the function will loss it's constexpr-ness.

Note that in the above code arbitrary_number should be constant expression as well, or else it will not compile.

like image 69
Nawaz Avatar answered Nov 16 '22 02:11

Nawaz


constexpr functions may be evaluated at compile time, it's not forced by the standard in general (you can force the function to be evaluated at compile time by using it inside a constant expression like initializing a constexpr variable with it).

Also, the arguments of a constexpr function are in fact not constant, they may change with every call (even if evaluated at compile time).

One work around is to use a non-type template to pass bar, if it's always a compile time constant (which it seems to be).

like image 45
Xeo Avatar answered Nov 16 '22 03:11

Xeo