decltypefun用于约束方法

问题描述

请考虑以下代码。我可以使用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,那么Clang会抱怨std::remove_cvref_t<decltype(fun())>

错误:在立即调用之外无法获取同代函数“ fun”的地址

GCC编译就可以了。为什么?

解决方法

正如在问题评论中已经说过的,这是CLang错误。

仅当函数是静态方法时才出现此错误,如果它是全局函数则代码可以工作(请参见工作online example here)。

因此,解决此问题的一种方法是使用全局函数转发静态方法的结果。我在下面做了一个更高级的此类全局转发示例。

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;
}