decltype(fun()) для методов consteval
Рассмотрим следующий код. Я могу скомпилировать его с помощью GCC 10.2.0 и Clang 11.0.0 (как и ожидалось):
#include <iostream>
template<int>
struct T {
static constexpr auto fun() noexcept { return 0; }
using type = std::remove_cvref_t<decltype(fun())>;
};
int main() {
decltype(T<1>::fun()) a = 1;
std::cout << a;
}
Если я заменю
constexpr
с участием
consteval
, то Кланг жалуется на
std::remove_cvref_t<decltype(fun())>
:
ошибка: невозможно взять адрес consteval функции 'fun' вне непосредственного вызова
GCC скомпилирует его просто отлично. Почему?
1 ответ
Как уже было сказано в комментариях к вопросу, это ошибка CLang.
Эта ошибка появляется, только если функция является статическим методом, если это глобальная функция, тогда код работает (см. Рабочий онлайн-пример здесь).
Следовательно, один из способов исправить это - использовать глобальную функцию для пересылки результата статического метода. Ниже я привел более сложный пример такой глобальной переадресации.
#include <iostream>
#include <type_traits>
template <typename T, typename ... Args>
static consteval auto forward_fun(Args ... args) {
return T::fun(args...);
}
template <int I>
struct T {
static consteval auto fun(int i, bool f) noexcept {
return i + 1;
}
using type = std::remove_cvref_t<decltype(forward_fun<T>(123, true))>;
};
int main() {
T<1>::type a = 1;
std::cout << a;
return 0;
}