Consider the following code. I can compile it with GCC 10.2.0 and Clang 11.0.0 (as expected):
#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;
}
If I replace constexpr
with consteval
, then Clang complains about std::remove_cvref_t<decltype(fun())>
:
error: cannot take address of consteval function 'fun' outside of an immediate invocation
GCC compile it just fine. Why?
As already said in comments to question, this is CLang bug.
This bug appears only if a function is a static method, if it is a global function then code works (see working online example here).
Hence one way to fix this is to use global function to forward result of static method. I did a bit more advanced example of such global forwarding below.
#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;
}