c++ - 类型特征 : Check if class have specific function (maybe inherit)

标签 c++ c++11 typetraits

我知道有很多方法可以检测一个类是否具有特定功能,但没有一种方法真正适合我的具体情况。我当前用于检查正确成员函数的实现工作正常,继承函数除外。

#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.

此实现不适用于 B 的 static_assert。

一个 Not Acceptable 解决方法是检查:

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

但是我必须知道基类,这应该避免。

有没有人知道如何同时检查派生函数?

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

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

最佳答案

这是一种方法(适用于您的 4 个测试用例,虽然没有对其进行密集测试),感谢@Jarod42 的改进(请参阅最后的初始答案):

template <typename T>
int call_foo (int (T::*)(float));

template <typename C>
std::true_type has_foo(decltype(call_foo(&C::foo)));

template <typename C>
std::false_type has_foo (...);    

template<typename T>
using HasFoo = decltype(has_foo<T>(0));

您的代码的问题是您期望 U::*&B::fooA::*(不是B::*)。在这里,我让编译器使用隐式类型推导来选择 T 的值,这样我就不会遇到这样的问题。

代码工作如下:

  • 如果T 没有foo 成员,那么编译器将选择has_foo 的第二个重载。
  • 如果 T 确实有一个 foo 成员,编译器将尝试第一次重载但会失败,因为没有匹配的 call_foo 函数所以它将再次选择第二个并创建一个 std::false_type

ideone 上的工作代码:http://ideone.com/erh93I .

如果你愿意,你可以把所有东西都放在一个中:

template <typename T>
class HasFoo {

    template <typename C>
    static int call_foo (int (C::*)(float));

    template <typename C>
    static std::true_type has_foo (decltype(call_foo(&C::foo)));

    template <typename C>
    static std::false_type has_foo (...);

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

关于c++ - 类型特征 : Check if class have specific function (maybe inherit),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36692345/

相关文章:

c++ - 为什么我的特征模板类查找 operator<< 不能用于 llvm::StringRef?

c++ - 使用声明可以在 gcc 和 msvc 中编译,但在 clang 中被拒绝

c++ - ICreateDevEnum 在 32 位上工作但在 64 位上失败

c++ - 如果我有一个嵌套映射作为多映射的值,我如何将值插入内部映射?

c++ - 现在如何在 C++11 中编写 for 循环?

c++ - 编译器对编译时分支有什么作用?

c++ - 如何调试由类型特征引起的这个错误?

c++ - 如何在其他文件(foo.h、foo.cpp)中使用主文件 (main.cpp) 中的变量?

c++ - 如何在 cmake 中启用 `/std:c++latest`?

c++ - 用 g++/bison/boost::variant 编写的解析器编译速度很慢