Suppose I have a constexpr array of function pointers, and I want to write a constexpr function to find the array index for a specified function.
I might have code like this:
void test1(){}void test2(){}void test3(){}void test4(){}
typedef void(*func)(void);
constexpr func funcs[] = { &test1, &test2, &test3 };
constexpr int FindMatchingIdx (const func work, const int idx) {
return (work == funcs[idx]) ? (idx) : (FindMatchingIdx(work, idx + 1));
}
constexpr unsigned int loc = FindMatchingIdx (&test1,0);
Now this code compiles on Clang and MSVC, however GCC will only compile when FindMatchingIdx
is called with the first element in the array. If FindMatchingIdx
is called with test1
, GCC will compile the code, however if FindMatchingIdx
is called with test2
or test3
GCC will fail to compile the code, giving the error message:
error: '(test1 != test2)' is not a constant expression.
If FindMatchingIdx
has to recurse, GCC will fail to treat it as a constexpr function. Is this a bug in GCC? How does function pointer comparison even work inside a constexpr function? Obviously it can't be using real pointer values as those are assigned by the linker.
Working example: https://godbolt.org/g/xfv1PM
A call to a constexpr function produces the same result as a call to an equivalent non- constexpr function , except that a call to a constexpr function can appear in a constant expression. The main function cannot be declared with the constexpr specifier.
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.
Even though try blocks and inline assembly are allowed in constexpr functions, throwing exceptions or executing the assembly is still disallowed in a constant expression.
I do not know if this is why gcc is complaining, but there is some arguable ambiguity in the standard about if test1
and test2
have distinct addresses, and hence compare equal.
If the standard is actually ambiguous there, then gcc is right in saying test1 != test2
is unspecified by the standard. Meanwhile, test1==test1
is specified by the standard.
The inequality of function pointers being like that has the benefit that it permits the compiler to assign two distinct functions with identical binary implementations the same address. So test1
and test2
and test3
would be distinct functions with the same address, and pointers to them would compare equal.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With