我想检查 SFINAE 是否定义了类的特定成员函数,并且同时未禁用该函数。以下代码有效:
struct A {
int foo() { return 3; }
};
struct B {};
template <class, class = void>
struct hasFoo : std::false_type {};
template <class T>
struct hasFoo<T, std::void_t<decltype(std::declval<T>().foo())>>
: std::true_type {};
template <class T>
struct hasFoo20 : std::bool_constant < requires(T t) {
t.foo();
} > {};
static_assert(hasFoo<A>::value);
static_assert(!hasFoo<B>::value);
static_assert(hasFoo20<A>::value);
static_assert(!hasFoo20<B>::value);
但是如果我在
A
中有一个成员函数,它本身是使用 SFINAE 启用或禁用的,则我无法使其正常工作:
template <typename T = int>
struct A {
template <typename = void, std::enable_if_t<std::is_same_v<T, int>, bool> = true>
T foo() {
return 3;
}
};
template <class, class = void>
struct hasFoo : std::false_type {};
template <class T>
struct hasFoo<T, std::void_t<decltype(std::declval<T>().foo())>>
: std::true_type {};
template <class T>
struct hasFoo20 : std::bool_constant < requires(T t) {
t.foo();
} > {};
static_assert(hasFoo<A<>>::value);
static_assert(!hasFoo<A<double>>::value);
static_assert(hasFoo20<A<>>::value);
static_assert(!hasFoo20<A<double>>::value);
链接 对于第二种情况,只有 C++20 代码可以按我想要的方式工作,但我必须使其兼容 C++17。
SFINAE 代码失败并显示
error: no type named 'type' in 'struct std::enable_if<false, bool>'
,这是预期的,因为计算了 enable_if_t
的 foo
。
有人可以给我提示吗?谢谢!
SFINAE 必须依赖于它出现的模板参数。尽管
T
看起来像模板参数,但它来自封闭类。
一个解决方案是
template <typename U = T, std::enable_if_t<std::is_same_v<U, int>, bool> = false>
T foo() {
return 3;
}