允许在constexpr函数中比较Is函数指针

Is function pointer comparison in a constexpr function allowed?

本文关键字:函数 比较 Is 指针 constexpr      更新时间:2023-10-16

假设我有一个constexpr函数指针数组,我想写一个constexpr函数来查找指定函数的数组索引。

我可能有这样的代码:

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);

现在这段代码可以在Clang和MSVC上编译,但是GCC只会在使用数组中的第一个元素调用FindMatchingIdx时编译。如果用test1调用FindMatchingIdx, GCC将编译代码,但是如果用test2test3调用FindMatchingIdx, GCC将编译代码失败,给出错误信息:

error: '(test1 != test2)'不是一个常量表达式。

如果FindMatchingIdx必须递归,GCC将无法将其视为constexpr函数。这是GCC中的一个bug吗?函数指针比较是如何在constexpr函数内工作的?显然,它不能使用真正的指针值,因为这些值是由链接器分配的。

工作示例:https://godbolt.org/g/xfv1PM

我不知道这是否是 gcc抱怨的原因,但是在标准中关于test1test2是否有不同的地址,因此比较相等的问题上存在一些可争议的歧见。

如果标准在这里实际上是模棱两可的,那么gcc说test1 != test2没有被标准指定是正确的。同时,test1==test1由标准指定。

函数指针的不等式是这样的,它允许编译器为具有相同二进制实现的两个不同的函数分配相同的地址。因此,test1test2test3将是具有相同地址的不同函数,并且指向它们的指针将比较相等。