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?

3
  • Oops, totally forgot to codify that part. Thanks @Henrik Commented Mar 20, 2012 at 15:40
  • 7
    A constexpr function can be called with non-const arguments, it simply forfeits its constexpr'ness. Commented Mar 20, 2012 at 15:40
  • possible duplicate of C++11 - static_assert within constexpr function? Commented Jun 11, 2012 at 15:02

3 Answers 3

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.

Sign up to request clarification or add additional context in comments.

1 Comment

what type of syntax is template<int bar>? a full template specialization like template <> ...?
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).

Comments

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.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.