检查是否存在C++成员函数,可能受到保护

Azo*_*oth 35 c++ final sfinae template-meta-programming c++11

我正在尝试检测一个类是否具有特定的功能(具体来说shared_from_this(),是继承自哪个std::enable_shared_from_this<Some Unknown Class>).为了使事情变得更复杂,我需要知道它是否具有此功能,即使它已从远程基类继承或使用受保护访问继承.

我已经查看了其他问题,例如这个问题,但提供的方法不适用于检测受保护的成员函数.

我目前使用的方法如下:

template <class T>
struct shared_from_this_wrapper : public T
{
  template <class U>
  static auto check( U const & t ) -> decltype( t.shared_from_this(), std::true_type() );

  static auto check( ... ) -> decltype( std::false_type() );
};

template<class T>
struct has_shared_from_this : decltype(shared_from_this_wrapper<T>::check(std::declval<shared_from_this_wrapper<T>>()))
{ };
Run Code Online (Sandbox Code Playgroud)

我当前解决方案的缺陷是它不适用于声明的类final.所以我正在寻找一个满足以下成员函数的测试解决方案:

  1. 适用于声明的类 final
  2. 使用受保护的成员函数
  3. 适用于继承
  4. 不需要知道函数的返回类型
  5. 在gcc,clang和MSVC 2013下编译(最后一个可能限制过于花哨的SFINAE)

编辑:我有一个可行的解决方案,但需要与帮助类成为朋友,这也不是一个理想的解决方案,但现在可能是一种解决方法(因为它满足所有要求):

struct access
{
  template <class T>
  static auto shared_from_this( T const & t ) -> decltype( t.shared_from_this() );
};

template <class U>
static auto check( U const & t ) -> decltype( access::shared_from_this(t), std::true_type() );

static auto check( ... ) -> decltype( std::false_type() );

template<class T>
struct has_shared_from_this2 : decltype(check(std::declval<T>()))
{ };

struct A : std::enable_shared_from_this<A> {};
struct B : protected A { friend class access; };    
Run Code Online (Sandbox Code Playgroud)

另一个编辑:类的示例和类型特征检查存在类似的东西shared_from_this应该返回:

struct A : std::enable_shared_from_this<A> {}; // should return true
struct B final : protected A {}; // should return true
struct C : A {}; // should return true
struct D {}; // should return false
Run Code Online (Sandbox Code Playgroud)

我应该提到我检测这个函数是否存在的最终目的是确定它的返回类型,以便找出std::enable_shared_from_this模板化的类型.继承std::enable_shared_from_this<T>给你std::shared_ptr<T> shared_from_this(),并且T最终我需要弄清楚.这对于继承的类型的正确序列化是必需的std::enable_shared_from_this.

编辑第3部分:编辑:

这是为序列化库谷物做的,因此我无法控制用户想要如何设计他们的类.我希望能够序列化任何派生的用户类型std::enable_shared_from_this,其中包括将其类声明为final或在此过程中使用受保护继承的用户.任何需要干预所检查的实际类型的解决方案都不是有效的解决方案.

ibi*_*man -1

如果唯一的目标是检测类型 T,那么我建议您像在 STL 中那样添加 typedef:

template <class T>
struct enable_shared_from_this : public T
{
    typedef T base_type;
    // ...
};
Run Code Online (Sandbox Code Playgroud)

然后你可以像这样使用它:

class A : enable_shared_from_this<B>
{
}

A::base_type // == B
Run Code Online (Sandbox Code Playgroud)

此示例假设您知道A 继承自shared_from_this_wrapper.