Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

__builtin_round is not a constant expression

In G++, various builtin math functions are constexpr under certain conditions. For example, the following compiles:

static constexpr double A = __builtin_sqrt(16.0);
static constexpr double B = __builtin_pow(A, 2.0);

They are not always constexpr though, it depends on the argument. For example, __builtin_sqrt(NAN) results in a compile error when used as a constant expression.

But I'm hitting a strange case where it seems to me that it should be constexpr, but it is not:

static constexpr double value () { return 1.23; }
static constexpr double result = __builtin_round(__builtin_sqrt(value()));

This produces:

a.cpp:2:73: error: ‘__builtin_round(1.1090536506409416e+0)’ is not a constant expression
 static constexpr double result = __builtin_round(__builtin_sqrt(value()));
                                                                         ^

I've tried variations of the above code, and I've found that:

  • The __builtin_round has some special role in the problem. Replacing it with some other builtin math function, such as sqrt or pow resolves the error. So would appear that __builtin_round simply lacks constexpr support. But...
  • If value() is replaced by a literal 1.23, that too removes the error.
  • Removing __builtin_sqrt, leaving only __builtin_round(value()), removes the error too.

I'd like to know why the round is behaving in this way, and if there is any workaround.

NOTE. I am aware that the builtin math functions, with their constexpr-ness, are a non-standard compiler-specific feature. Please don't lecture me on how I should not be using this, or how I shouldn't be trying to do compile time math. In my case, having constexpr math is an important feature, and I'm fine with depending on G++.

like image 697
Ambroz Bizjak Avatar asked May 03 '14 17:05

Ambroz Bizjak


People also ask

What is a constant expression?

A constant expression is an expression that contains only constants. A constant expression can be evaluated during compilation rather than at run time, and can be used in any place that a constant can occur.

What is the constant expression in c++?

A constant value is one that doesn't change. C++ provides two keywords to enable you to express the intent that an object is not intended to be modified, and to enforce that intent. C++ requires constant expressions — expressions that evaluate to a constant — for declarations of: Array bounds.


1 Answers

I have an idea of another workaround.

There is: use a helper function pass_through

template<typename T>
constexpr T&& pass_through (T&& t) { return static_cast<T&&>(t); }

use it like this:

static constexpr double value () { return 1.23; }
static constexpr double result = __builtin_round(pass_through(__builtin_sqrt(value())));

This code is compiled without error in the G++.

I also agree, the opinion that this issue should be reported to the GCC.

like image 118
Bolero MURAKAMI Avatar answered Nov 15 '22 19:11

Bolero MURAKAMI