已知 c++是不支持类似 java 的反射的,那么如果我们想知道一个类是否有某些成员,我们该怎么办呢,下面引入 c++模板编程技巧来,提供一个相对可行的办法
#include <iostream>
#include <algorithm>
using namespace std;
template<typename F, typename ...Args>
struct isInvokeAble {
public:
template<typename U, typename = decltype(declval<U>()(declval<Args>()...))>
static true_type test(void *);
template<typename U>
static false_type test(...);
public:
constexpr static auto value = decltype(test<F>(nullptr))::value;
};
class funcValidPolicy {
public:
template<typename F, typename ... Args>
static false_type Valid(...);
template<typename F, typename ... Args, typename = decltype(declval<F>()(declval<Args>()...))>
static true_type Valid(void *);
};
template<typename T>
struct TypeT {
using type = T;
};
template<typename T>
constexpr auto type = TypeT<T>{};
template<typename T>
T ValueT(TypeT<T>);
auto is_valid = [](auto f) {
return [](auto ...args) {
return decltype(funcValidPolicy::template Valid<decltype(f), decltype(args)...>(nullptr)){};
//return isInvokeAble<decltype(f), decltype(args)...>::value;
};
};
// 判断类是否有 first()函数
auto has_first_func = is_valid(
[](auto t) -> decltype(ValueT(t).first()) {}
);
struct First_Func {
void first() {
cout << "XX::first" << endl;
}
};
// 判读类是否有 first变量
auto has_first_member_value = is_valid(
[](auto t) -> decltype(ValueT(t).first) {}
);
struct First_Mem {
int first;
};
// 判断类是否可构造
auto isConstructible = is_valid(
[](auto t)-> decltype(decltype(ValueT(t))()){}
);
struct CanConstruct {};
struct CanNotConstruct {
private:
CanNotConstruct() = default;
};
int main() {
cout << has_first_func(type<First_Func>) << endl;
cout << has_first_member_value(type<First_Mem>) << endl;
cout << isConstructible(type<CanConstruct>) << endl;
cout << isConstructible(type<CanNotConstruct>) << endl;
}
输出