类型特征:检查类是否具有特定功能(可能继承) [英] Type trait: Check if class have specific function (maybe inherit)

查看:51
本文介绍了类型特征:检查类是否具有特定功能(可能继承)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我知道有很多可能的方法来检测类是否具有特定的功能,但对于我的具体情况,它们中的任何一种都不起作用。我当前执行的检查成员函数正确的实现,继承函数除外。

  #include< type_traits> 

template< typename T>
class HasFoo {
template< typename U,int(U :: *)(float)>
结构检查;

模板< typename U>
静态std :: true_type测试(Check< U,& U :: foo> *);

模板< typename U>
静态std :: false_type测试(...);

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

结构A {
int foo(float);
};

结构B:公共A {
};

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

结构D {
static int foo(float);
};

static_assert(HasFoo< A> :: value, A应该有foo。);
static_assert(HasFoo< B> :: value, B应该从A继承foo。);

static_assert(!HasFoo< C> :: value, C不应有foo。);
static_assert(!HasFoo< D> :: value, Ds静态foo应该为false。);

在线示例。



此实现不适用于B的static_assert。 / p>

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

  template<类型名U,int(U :: A :: *)(float)> 
结构检查; |
|-添加基类

但是在那里我必须知道基类应该避免。



有人有想法也要检查派生函数吗?



编辑:
如果根本不存在Foo,则类型特征也应该起作用。

  struct E { }; 
static_assert(!HasFoo< E> :: value, E没有foo。);


解决方案

这里是一所老学校 C ++ 03 方法。通常,它可以用作实用程序,并使其模制成任何方法或变量

 #定义HasMember(NAME)\ 
template< class类,类型名Type = void> \
struct HasMember _ ## NAME \
{\
typedef char(&yes)[2]; \
template< unsigned long>结构存在; \
template< typename V>静态是检查(存在< sizeof(static_cast< Type>(& V :: NAME))> *); \
template< typename>静态字符检查(...); \
静态常量值=(sizeof(Check< Class>(0))== sizeof(yes)); \
}; b
template< class Class> \
结构HasMember _ ## NAME< Class,void> \
{\
typedef char(&yes)[2]; \
template< unsigned long>结构存在; \
template< typename V>静态是检查(存在< sizeof(& V :: NAME)> *); \
template< typename>静态字符检查(...); \
静态常量值=(sizeof(Check< Class>(0))== sizeof(yes)); \
}

实例化:

  HasMember(Foo); 

用法

  HasMember_Foo< B> :: value //不带类型(但不允许重载)
HasMember_Foo< C,int(C :: *)(float)> :: value //需要输入

请注意,这里我提供了两个 HasMember_Foo s,带类型的1和带类型的1。它们适用于任何类型(不仅限于 int(X :: *)(float))。如果没有提到类型,则该类必须只有1个这样的方法(没有重载)。因此,提及类型总是比较安全的;正如您在问题中所做的那样,特定类型为 int(X :: *)(float)。顺便说一句,也可以使用另一个宏将其包括在内。

如果没有这样的额外宏,则在类C 类D中,您可能必须指定方法的类型。



这里是演示和您的代码。






此处假定任何一个班级成员(函数或变量)被选择,必须在 public 范围内。即,如果 X :: foo private ,则此解决方案将不起作用。


I know that there are many possible ways to detect if a class has a specific function but non of them really work for my exact case. My current implementation to check for the correct member function works, except for inherit functions.

#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.");

Live example.

This implementation does not work for the static_assert of B.

An inacceptable workaround would be to check for:

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

But there I would have to know the base class and this should be avoided.

Does anyone have an idea how to check also for derivated functions?

Edit: The type trait should also work if no Foo at all exist.

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

解决方案

Here is one old school C++03 way of doing it. Typically it can be used as a utility and get it molded for any method or variable.

#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)); \
  }

Instantiate:

HasMember(Foo);

Usage:

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

Note that, here I am providing two HasMember_Foos, 1 with type and 1 without type. They are generalized for any type (not just specific to int (X::*)(float)). If there is no type mentioned, then the class must have only 1 such method (without overload). Hence, it's always safer to mention the type; As you have done in your question, the specific type is int (X::*)(float). BTW, this also can be included using another macro.
Without such extra macro, in case of class C and class D, you may have to specify the type of the method.

Here is a demo with your code.


Here it's assumed that whichever class member (function or variable) is chosen, must be public scoped. i.e. If X::foo is private then this solution will not work.

这篇关于类型特征:检查类是否具有特定功能(可能继承)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆