Возможно ли сравнение указателей на функции в функции constexpr?
Предположим, что у меня есть массив 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 не сможет скомпилировать код, указав сообщение об ошибке:
error: '(test1!= test2)' не является постоянным выражением.
Если FindMatchingIdx
должен возвращаться, GCC не сможет обработать его как функцию constexpr. Это ошибка в GCC? Как сравнение указателя функции даже работает внутри функции constexpr? Очевидно, что он не может использовать реальные значения указателя, поскольку они назначаются компоновщиком.
Рабочий пример: https://godbolt.org/g/xfv1PM
Ответы
Ответ 1
Я не знаю, является ли это причиной того, что gcc жалуется, но есть некоторая сомнительная двусмысленность в стандарте о том, имеют ли test1
и test2
разные адреса, и, следовательно, сравните равные.
Если стандарт там действительно двусмыслен, то gcc прав, говоря, что test1 != test2
не указывается стандартом. Между тем, test1==test1
указывается стандартом.
Неправильное использование указателей функций имеет то преимущество, что позволяет компилятору назначать две разные функции с идентичными бинарными реализациями одного и того же адреса. Таким образом, test1
и test2
и test3
будут различными функциями с одинаковым адресом, а указатели на них будут сравнивать равные.