假设我有一个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
时进行编译。如果使用FindMatchingIdx
调用test1
,GCC将编译代码,但是如果使用FindMatchingIdx
或test2
调用test3
,GCC将无法编译代码,给出错误信息:
错误:'(test1!= test2)'不是常量表达式。
如果FindMatchingIdx
必须递归,GCC将无法将其视为constexpr函数。这是GCC中的错误吗?函数指针比较如何在constexpr函数内部工作?显然它不能使用真实的指针值,因为它们是由链接器分配的。
答案 0 :(得分:2)
我不知道这是为什么 gcc正在抱怨,但标准中有some arguable ambiguity关于test1
和test2
是否有不同的地址,因此比较平等。
如果标准在那里实际上是模糊的,那么gcc是正确的说test1 != test2
未被标准指定。同时,test1==test1
由标准指定。
函数指针的不等式具有以下优点:它允许编译器将相同二进制实现的两个不同函数分配给相同的地址。因此,test1
和test2
以及test3
将是具有相同地址的不同函数,并且指向它们的指针将相等。