6

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?

Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
Koosha
  • 1,492
  • 7
  • 19
  • 1
    It's a [clang bug](https://bugs.llvm.org/show_bug.cgi?id=47350). See the linked [proposal](http://open-std.org/JTC1/SC22/WG21/docs/papers/2020/p1937r2.html) that has basically the same example as your code. – cigien Nov 10 '20 at 04:30

1 Answers1

1

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;
}
Arty
  • 14,883
  • 6
  • 36
  • 69