How to tell static_assert that constexpr function arguments are const?
Asked Answered
F

3

9

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?

Forbidding answered 20/3, 2012 at 15:37 Comment(3)
Oops, totally forgot to codify that part. Thanks @HenrikForbidding
A constexpr function can be called with non-const arguments, it simply forfeits its constexpr'ness.Kosher
possible duplicate of C++11 - static_assert within constexpr function?Steiner
T
17

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.

Ticknor answered 20/3, 2012 at 15:43 Comment(1)
what type of syntax is template<int bar>? a full template specialization like template <> ...?Substitute
D
5

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

Devondevona answered 20/3, 2012 at 15:44 Comment(0)
T
0

foo can be used in the following manner:

int i;
std::cin >> i;
foo("foo", i);

As you can see i isn't exactly a constant expression above, yet it can still be used with a constexpr functions. constexpr functions (and function templates) are a strange beast that guarantee that e.g. foo(p, i) is a constant expression iff p and i also are, but can still be used like regular functions.

If arguments to your functions are truly meant to always be constant expressions, then they should be template arguments, not function arguments.

Triode answered 20/3, 2012 at 15:44 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.