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;
}
Другие вопросы по тегам