类型特征:检查类是否具有特定功能(可能是继承)

Via*_*rus 7 c++ type-traits c++11

我知道有很多可能的方法可以检测一个类是否具有特定的功能但是它们的确不适用于我的确切情况.除了继承函数之外,我当前检查正确成员函数的实现是否有效.

#include <type_traits>

template<typename T>                                                                
class HasFoo {                                                                                 
    template <typename U, int (U::*)(float)>                                  
      struct Check;                                                                 

    template <typename U>                                                       
      static std::true_type Test(Check<U, &U::foo> *);                 

    template <typename U>                                                           
      static std::false_type Test(...);                                               

public:
    static constexpr bool value = decltype(Test<T>(0))::value;                    
};

struct A {
  int foo(float);
};

struct B : public A {
};

struct C {
  unsigned int foo(double);
};

struct D {
  static int foo(float);
};

static_assert(HasFoo<A>::value, "A should have foo.");
static_assert(HasFoo<B>::value, "B should inherit foo from A.");

static_assert(!HasFoo<C>::value, "C should not have foo.");
static_assert(!HasFoo<D>::value, "Ds static foo should be false.");
Run Code Online (Sandbox Code Playgroud)

实例.

此实现不适用于B的static_assert.

一个不可接受的解决方法是检查:

template <typename U, int (U::A::*)(float)>
struct Check;                 |
                              |- add base class
Run Code Online (Sandbox Code Playgroud)

但在那里我必须知道基类,这应该避免.

有没有人知道如何检查衍生函数?

编辑: 如果根本不存在Foo,那么类型特征也应该有效.

struct E {};
static_assert(!HasFoo<E>::value, "E does not have foo.");
Run Code Online (Sandbox Code Playgroud)

iam*_*ind 3

这是一种老式的C++03方法。通常,它可以用作实用程序并为任何方法或变量建模。

#define HasMember(NAME) \
  template<class Class, typename Type = void> \
  struct HasMember_##NAME \
  { \
    typedef char (&yes)[2]; \
    template<unsigned long> struct exists; \
    template<typename V> static yes Check (exists<sizeof(static_cast<Type>(&V::NAME))>*); \
    template<typename> static char Check (...); \
    static const bool value = (sizeof(Check<Class>(0)) == sizeof(yes)); \
  }; \
  template<class Class> \
  struct HasMember_##NAME<Class, void> \
  { \
    typedef char (&yes)[2]; \
    template<unsigned long> struct exists; \
    template<typename V> static yes Check (exists<sizeof(&V::NAME)>*); \
    template<typename> static char Check (...); \
    static const bool value = (sizeof(Check<Class>(0)) == sizeof(yes)); \
  }
Run Code Online (Sandbox Code Playgroud)

实例化:

HasMember(Foo);
Run Code Online (Sandbox Code Playgroud)

用法

HasMember_Foo<B>::value  // without type (but then no overload allowed)
HasMember_Foo<C, int (C::*)(float)>::value  // needs type
Run Code Online (Sandbox Code Playgroud)

请注意,这里我提供了两个HasMember_Foos,1 个带类型,1 个不带类型。它们适用于任何类型(不仅仅是特定于int (X::*)(float))。如果没有提到类型,则该类必须只有 1 个这样的方法(无重载)。因此,提及类型总是更安全;正如您在问题中所做的那样,具体类型是int (X::*)(float). 顺便说一句,这也可以使用另一个宏来包含。如果没有这样的额外宏,在and
的情况下,您可能必须指定方法的类型。class Cclass D

这是包含您的代码的演示


这里假设无论选择哪个类成员(函数或变量),都必须有public作用域。即如果X::fooprivate那么这个解决方案将不起作用。