Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++11 - static_assert within constexpr function?

How would one properly do a static_assert within a constexpr function? For example:

constexpr int do_something(int x)
{
  static_assert(x > 0, "x must be > 0");
  return x + 5;
}

This is not valid C++11 code, because a constexpr function must only contain a return statement. I don't think that the standard has an exception to this, although, the GCC 4.7 does not let me compile this code.

like image 541
RétroX Avatar asked Dec 24 '11 18:12

RétroX


People also ask

What is constexpr in C++11?

The keyword constexpr was introduced in C++11 and improved in C++14. It means constant expression. Like const , it can be applied to variables: A compiler error is raised when any code attempts to modify the value. Unlike const , constexpr can also be applied to functions and class constructors.

Can you modify constexpr?

A const int var can be dynamically set to a value at runtime and once it is set to that value, it can no longer be changed. A constexpr int var cannot be dynamically set at runtime, but rather, at compile time. And once it is set to that value, it can no longer be changed.

Where is Static_assert defined?

static_assert is a keyword defined in the <assert. h> header. It is available in the C11 version of C. static_assert is used to ensure that a condition is true when the code is compiled.

How do I know if a function is constexpr?

The easiest way to check whether a function (e.g., foo ) is constexpr is to assign its return value to a constexpr as below: constexpr auto i = foo(); if the returned value is not constexpr compilation will fail.


2 Answers

This is not valid C++11 code, because a constexpr function must only contain a return statement.

This is incorrect. static_assert in a constexpr function are fine. What is not fine is using function parameters in constant expressions, like you do it.

You could throw if x <= 0. Calling the function in a context that requires a constant expression will then fail to compile

constexpr int do_something(int x) {   return x > 0 ? (x + 5) : (throw std::logic_error("x must be > 0")); } 
like image 185
Johannes Schaub - litb Avatar answered Oct 16 '22 03:10

Johannes Schaub - litb


This works and is valid C++11 code, because template arguments are compile time only:

template <int x> constexpr int do_something() {     static_assert(x > 0, "x must be > 0");     return x + 5; } 

I faced with the same problems as you did with constant expressions in C++. There's few clear documentation about constexprs at the moment. And note that there's some known bugs with it in gcc's issue tracker, but your problem seems not to be a bug.

Note that if you declare constexpr functions inside classes, you are not able to use them inside the class. This also seems to be not a bug.

Edit: This is allowed according to the standard: 7.1.3 states

... or a compound-statement that contains only

  • null statements,
  • static_assert-declarations
  • typedef declarations and alias-declarations that do not
    define classes or enumerations,
  • using-declarations,
  • using-directives,
  • and exactly one return statement
like image 33
cppist Avatar answered Oct 16 '22 02:10

cppist