如何检查成员函数或自由函数是否适用于确切的给定类型(而不是其任何基类)?

How to check if a member function or free function is for the exact given type(not any of its base)?

一种检查成员 function/free 函数是否可以在对象上调用的方法是:

#include <type_traits>
#include <utility>

template <class T, class = void>
struct HasMember : std::false_type {};
template <class T>
struct HasMember<T, std::void_t<decltype(std::declval<T>().Foo())>> : std::true_type {};

template <class T, class = void>
struct HasFreeFoo : std::false_type {};
template <class T>
struct HasFreeFoo<T, std::void_t<decltype(Foo(std::declval<T>()))>> : std::true_type {};

struct A { void Foo() {} }; 
struct B : A {};
struct C : B {};
                                          
void Foo(const A &) {}

int main() {
  static_assert(HasMember<C>::value, "");
  static_assert(HasFreeFoo<C>::value, "");
}

但如示例所示,

  1. C 被认为有成员 Foo 因为 A 已经实现了 Foo,
  2. C 被认为实现了自由函数 Foo,因为 Foo 接受 const A &.

我想要达到的是拥有HasMember<A>::value == true && HasMember<C>::value == falseHasFreeFoo<A>::value == true && HasFreeFoo<C>::value == false。欢迎任何帮助,谢谢。

背景: 我正在实现一个 ser/des 工具,用户可以选择实现一个成员函数或一个自由函数来指定一个类型应该如何获得 ser/des。而且我需要检查是否完全针对给定类型实现了这样的成员函数/自由函数(不是从其基础继承的)。

HasMemberHasFreeFoo的实现是合理的,因为C确实可以通过继承获得Foo()。你需要的是实现另一个特征来选择是通过成员函数还是自由函数调用。例如:

template <class T, class = void>
struct UseMemberFoo : std::false_type {};

template <class T>
struct UseMemberFoo<T, std::enable_if_t<HasMember<T>::value && !HasFreeFoo<T>::value>>
 : std::true_type { };

template<class T>
void Foo(const T&) = delete;

template <class T, class = void>
struct UseFreeFoo : std::false_type {};

template <class T>
struct UseFreeFoo<T, std::enable_if_t<HasMember<T>::value && HasFreeFoo<T>::value>>
 : std::true_type { };

T只有成员Foo()时,则通过成员函数调用。当用户继承有成员Foo()的基class并为派生class提供自由函数时,则通过自由函数调用。

Demo.