Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why can function pointers be `constexpr`?

How does the compiler know where in memory the square root will be before the program is executed? I thought the address would be different everytime the program is executed, but this works:

constexpr double(*fp)(double) = &sqrt; cout << fp(5.0); 

Is it because the address is relative to another address in memory? I don't think so because the value of fp is large: 0x720E1B94.

like image 394
Coolwater Avatar asked Jul 16 '16 15:07

Coolwater


People also ask

Can a pointer be constexpr?

C++'s constexpr brings another new dimension to the problem too! It behaves like const in the sense that it makes all pointers constant pointers. But because it occurs at the start of your statement (rather than after the '*') its not immediately obvious.

When can a function be constexpr?

A constexpr function is one whose return value is computable at compile time when consuming code requires it. Consuming code requires the return value at compile time to initialize a constexpr variable, or to provide a non-type template argument.

Why does constexpr need to be static?

A static constexpr variable has to be set at compilation, because its lifetime is the the whole program. Without the static keyword, the compiler isn't bound to set the value at compilation, and could decide to set it later.

Can a function return constexpr?

A constexpr function is a function that can be invoked within a constant expression. A constexpr function must satisfy the following conditions: It is not virtual. Its return type is a literal type.


1 Answers

At compile time, the compiler doesn't know the address of sqrt. However, you cannot do anything at compile time with a constexpr function pointer that would allow you to access that pointer's address. Therefore, a function pointer at compile time can be treated as an opaque value.

And since you can't change a constexpr variable after it has been initialized, every constexpr function pointer can be boiled down to the location of a specific function.

If you did something like this:

using fptr = float(*)(float);  constexpr fptr get_func(int x) {   return x == 3 ? &sqrtf : &sinf; }  constexpr fptr ptr = get_func(12); 

The compiler can detect exactly which function get_func will return for any particular compile time value. So get_func(12) reduces down to &sinf. So whatever &sinf would compile to is exactly what get_func(12) would compile to.

like image 55
Nicol Bolas Avatar answered Sep 19 '22 12:09

Nicol Bolas