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?
The consteval specifier declares a function or function template to be an immediate function, that is, every potentially evaluated call (i.e. call out of an unevaluated context) to the function must (directly or indirectly) produce a compile time constant expression.
Like the sizeof operator, decltype 's operand is not evaluated.
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.
Try it online!
#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;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With