检查成员函数是否是使用SFINAE而不是requires子句定义的

问题描述 投票:0回答:1

我想检查 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

有人可以给我提示吗?谢谢!

c++ c++17 sfinae requires-expression
1个回答
0
投票

SFINAE 必须依赖于它出现的模板参数。尽管

T
看起来像模板参数,但它来自封闭类。

一个解决方案是

template <typename U = T, std::enable_if_t<std::is_same_v<U, int>, bool> = false>
T foo() {
    return 3;
}
© www.soinside.com 2019 - 2024. All rights reserved.