有没有办法仅通过名称来检测重载的成员函数? (不检测名称)

Is there any way to detect overloaded member function by name alone? (not to detect name)

我在这里一厢情愿,但我想把问题说清楚。我想改进仅通过名称检测成员模板的实现,但我遇到了障碍。我找不到任何方法来检测重载的 static/非 static 成员函数。这个问题非常重要的部分是,我不能使用 this trick,因为它检测到任何名称(我已经在当前实现中使用它,有点用),而且我不能指定类型,因为那错过了单独使用名称的要点。

作为参考,请参阅我的 other question. I posted current has_member_template_bar implementation as an answer。我认为我不应该 post 在这个问题中全部回答。

问题仍然存在 - 我们能否在不指定参数或使用上述技巧的情况下检测重载的成员函数?我知道我问的可能是不可能的,但问总不会有坏处。

The question stays the same - Can we detect overloaded member functions, without specifying their arguments, or using mentioned trick? I know I'm maybe asking for impossible, but it never hurts to ask

其实也不是不可能。
它遵循一个最小的工作示例:

template<typename T, typename R, typename... A>
void proto(R(T::*)(A...));

template<typename, typename = void>
constexpr bool has_single_f = false;

template<typename T>
constexpr bool has_single_f<T, decltype(proto(&T::f))> = true;

struct S {
    void f(int) {}
    void f(char) {}
};

struct U {
    void f() {}
};

int main() {
    static_assert(not has_single_f<S>, "!");
    static_assert(has_single_f<U>, "!");
}

当然,你需要添加更多的东西来区分成员方法和数据成员,但是添加它们是微不足道的(参见 header type_traits),我试着保留这个例子尽可能少。

基本思想是,如果给定函数重载,对 proto 的调用将失败,因为它是一个 模棱两可的调用 .
Anyway,由于SFINAE规则错误被丢弃
不需要按要求指定参数。
还要注意 proto 不需要定义,但重要的是它的 return 类型是 void。否则,您必须稍微修改对 decltype 的调用,如下所示:

template<typename T>
constexpr bool has_single_f<T, decltype(proto(&T::f), void())> = true;

正如您从示例代码中看到的那样,static_asserts 验证 fS 中重载,而不是在 U.[=23 中=]


上面的例子基于模板变量,它是自 C++14 以来语言的一部分。
如果您更喜欢使用 C++11 的众所周知的基于结构的解决方案,您可以使用以下检测器:

#include<type_traits>

//...

template<typename, typename = void>
struct has_single_f: std::false_type {};

template<typename T>
struct has_single_f<T, decltype(proto(&T::f))>: std::true_type {};

//...

int main() {
    static_assert(not has_single_f<S>::value, "!");
    static_assert(has_single_f<U>::value, "!");
}