我知道有很多可能的方法来检测一个类是否具有特定的功能,但没有一种方法真正适合我的具体情况。我当前用于检查成员函数是否正确的实现,除了继承函数之外。
#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.");
活生生的例子。
此实现不适用于 B 的 static_assert。
不可接受的解决方法是检查:
template <typename U, int (U::A::*)(float)>
struct Check; |
|- add base class
但在那里我必须知道基类,这应该避免。
有谁知道如何检查派生函数?
Edit:如果根本不存在 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::foo
is A::*
(not B::*
)。这里我让编译器选择的值T
通过使用隐式类型推导,这样我就不会遇到这样的问题。
代码的工作原理如下:
- If
T
没有foo
成员,那么编译器将选择第二个重载has_foo
.
- If
T
确实有一个foo
成员,编译器将尝试第一个重载,但会失败,因为没有匹配的call_foo
函数,因此它将再次选择第二个并制作一个std::false_type
.
ideone 上的工作代码:http://ideone.com/erh93I.
你可以把所有东西都放在一个class
如果你想:
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)){};
};
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)