更新:我最近对我在原始答案中发布的代码进行了一些修改,因此我正在更新这个内容以适应更改/添加。
以下是一些使用片段:
*所有这些的关键部分都在下面
检查给定类中的成员x
。可以是变量、函数、类、联合或枚举:
CREATE_MEMBER_CHECK(x);
bool has_x = has_member_x<class_to_check_for_x>::value;
检查成员函数 void x()
:
//Func signature MUST have T as template variable here... simpler this way :\
CREATE_MEMBER_FUNC_SIG_CHECK(x, void (T::*)(), void__x);
bool has_func_sig_void__x = has_member_func_void__x<class_to_check_for_x>::value;
检查成员变量x
:
CREATE_MEMBER_VAR_CHECK(x);
bool has_var_x = has_member_var_x<class_to_check_for_x>::value;
检查成员类 x
:
CREATE_MEMBER_CLASS_CHECK(x);
bool has_class_x = has_member_class_x<class_to_check_for_x>::value;
检查成员联合体x
:
CREATE_MEMBER_UNION_CHECK(x);
bool has_union_x = has_member_union_x<class_to_check_for_x>::value;
检查成员枚举 x
:
CREATE_MEMBER_ENUM_CHECK(x);
bool has_enum_x = has_member_enum_x<class_to_check_for_x>::value;
检查任何成员函数x
,无论签名如何:
CREATE_MEMBER_CHECK(x);
CREATE_MEMBER_VAR_CHECK(x);
CREATE_MEMBER_CLASS_CHECK(x);
CREATE_MEMBER_UNION_CHECK(x);
CREATE_MEMBER_ENUM_CHECK(x);
CREATE_MEMBER_FUNC_CHECK(x);
bool has_any_func_x = has_member_func_x<class_to_check_for_x>::value;
或者
CREATE_MEMBER_CHECKS(x); //Just stamps out the same macro calls as above.
bool has_any_func_x = has_member_func_x<class_to_check_for_x>::value;
细节和核心:
template <typename... Args> struct ambiguate : public Args... {};
template<typename A, typename = void>
struct got_type : std::false_type {};
template<typename A>
struct got_type<A> : std::true_type {
typedef A type;
};
template<typename T, T>
struct sig_check : std::true_type {};
template<typename Alias, typename AmbiguitySeed>
struct has_member {
template<typename C> static char ((&f(decltype(&C::value))))[1];
template<typename C> static char ((&f(...)))[2];
static_assert(
(sizeof(f<AmbiguitySeed>(0)) == 1)
, "Member name specified in AmbiguitySeed is different from member name specified in Alias, or wrong Alias/AmbiguitySeed has been specified."
);
static bool const value = sizeof(f<Alias>(0)) == 2;
};
宏 (魔鬼!):
CREATE_MEMBER_CHECK:
(创建成员检查)
//Check for any member with given name, whether var, func, class, union, enum.
\
template<typename T, typename = std::true_type> \
struct Alias_
\
template<typename T> \
struct Alias_
T, std::integral_constant<bool, got_type<decltype(&T::member)>::value> \
> { static const decltype(&T::member) value
\
struct AmbiguitySeed_
\
template<typename T> \
struct has_member_
static const bool value \
= has_member< \
Alias_
, Alias_
>::value \
}
CREATE_MEMBER_VAR_CHECK:
//Check for member variable with given name.
\
template<typename T, typename = std::true_type> \
struct has_member_var_
\
template<typename T> \
struct has_member_var_
T \
, std::integral_constant< \
bool \
, !std::is_member_function_pointer<decltype(&T::var_name)>::value \
> \
> : std::true_type {}
CREATE_MEMBER_FUNC_SIG_CHECK:
//Check for member function with given name AND signature.
\
template<typename T, typename = std::true_type> \
struct has_member_func_
\
template<typename T> \
struct has_member_func_
T, std::integral_constant< \
bool \
, sig_check<func_sig, &T::func_name>::value \
> \
> : std::true_type {}
CREATE_MEMBER_CLASS_CHECK:
//Check for member class with given name.
\
template<typename T, typename = std::true_type> \
struct has_member_class_
\
template<typename T> \
struct has_member_class_
T \
, std::integral_constant< \
bool \
, std::is_class< \
typename got_type<typename T::class_name>::type \
>::value \
> \
> : std::true_type {}
CREATE_MEMBER_UNION_CHECK:
//Check for member union with given name.
\
template<typename T, typename = std::true_type> \
struct has_member_union_
\
template<typename T> \
struct has_member_union_
T \
, std::integral_constant< \
bool \
, std::is_union< \
typename got_type<typename T::union_name>::type \
>::value \
> \
> : std::true_type {}
CREATE_MEMBER_ENUM_CHECK:
//Check for member enum with given name.
\
template<typename T, typename = std::true_type> \
struct has_member_enum_
\
template<typename T> \
struct has_member_enum_
T \
, std::integral_constant< \
bool \
, std::is_enum< \
typename got_type<typename T::enum_name>::type \
>::value \
> \
> : std::true_type {}
CREATE_MEMBER_FUNC_CHECK:
#define CREATE_MEMBER_FUNC_CHECK(func) \
template<typename T> \
struct has_member_func_##func { \
static const bool value \
= has_member_##func<T>::value \
&& !has_member_var_##func<T>::value \
&& !has_member_class_##func<T>::value \
&& !has_member_union_##func<T>::value \
&& !has_member_enum_##func<T>::value \
; \
}
CREATE_MEMBER_CHECKS:
//Create all the checks for one member. Does NOT include func sig checks.
CREATE_MEMBER_CHECK(member)
CREATE_MEMBER_VAR_CHECK(member)
CREATE_MEMBER_CLASS_CHECK(member)
CREATE_MEMBER_UNION_CHECK(member)
CREATE_MEMBER_ENUM_CHECK(member)
CREATE_MEMBER_FUNC_CHECK(member)