通过概念检查模板化静态方法

Checking for a templated static method via concepts

我想写一个概念来检查类型是否有一个名为 foo 的静态方法。该方法将有一个模板化参数(稍后将使用不同的参数类型多次调用该函数)。

由于该模板化参数,很难对其进行检查。一开始,我以为我只检查是否有同名的成员。

以下代码使用 Clang 编译,但不使用 GCC 编译,因为它无法解析重载函数的地址 T::foo.

template <typename T>
concept HasFoo = requires { T::foo; };

class Bar {
public:
    template <typename T>
    static void foo(T t);
};

static_assert(HasFoo<Bar>);

您如何正确检查模板化静态方法的存在(在 Clang 和 GCC 中工作)? 理想情况下,您甚至可以检查更多吗?就像检查 return 类型是否为 void,或者它是否可调用。

一种方法是将模板化类型包含到概念中,但因为我想将该方法用于多种不同的类型。 所以只检查一种类型,就像下面的代码一样,是不够的。

template <typename T, typename T2>
concept HasFoo = requires { T::template foo<T2>; };

static_assert(HasFoo<Bar, int>);

How do you correctly check for the existence of a templated static method (working in Clang and GCC)? And ideally, can you even check more than this? Like checking if the return type is void, or if it is callable.

I do have some constraints on template arguments, for the sake of the simplified example in the question we can just assume it's an integer type.

要检查 class 是否支持可使用整数和 return void 调用的静态模板方法 foo(),您可以简单地检查

template <typename T>
concept HasFoo = std::is_same_v<decltype(T::foo(0)), void>;

如果您还想确保 foo() 方法是模板方法,我想您还可以检查将 &T::foo 转换为不同的函数指针类型会得到不同的值,所以 (例如)

(    (void*)(&T::template foo<int>)
  != (void*)(&T::template foo<long>))

结合这两个要求,

template <typename T>
concept HasFoo =    (    (void*)(&T::template foo<int>)
                      != (void*)(&T::template foo<long>))
                 && std::is_same_v<decltype(T::foo(0)), void>;

struct Bar1 
 { template <typename T> static void foo (T) {} };

struct Bar2 
 { static void foo (int) {} };   

struct Bar3
 { template <typename T> static T foo; };

template <typename T>
T Bar3::foo;

struct Bar4
 { template <typename T> static int foo (T) { return 0; } };

你有

static_assert(HasFoo<Bar1>);
static_assert(not HasFoo<Bar2>); // not because foo() isn't template
static_assert(not HasFoo<Bar3>); // not because foo isn't callable
static_assert(not HasFoo<Bar4>); // not becasue foo() return int