由于所有答案对我来说都太复杂了,我想介绍我自己的解决方案,使用std::declval
and std::enable_if
(GCC 4.8.3)
#define MEMBER_FUNC_CHECKER(name, fn, ret, args) \
template<class C, typename=void> struct name : std::false_type {}; \
template<class C> struct name<C, typename std::enable_if< \
std::is_convertible<decltype(std::declval<C>().fn args), ret \
>::value>::type> : std::true_type {};
注意:不是对签名进行精确检查,而是对具有可转换返回类型的可调用函数进行检查。(编辑:从更改is_same
为is_convertible
)
测试
struct One {
int get() { return 0; }
int add(int x, int y) { return x+y; }
};
struct Two: One {};
struct Not {};
MEMBER_FUNC_CHECKER(has_get, get, int, ())
MEMBER_FUNC_CHECKER(has_add, add, int, (1,2))
int main() {
cout << "One " << (has_get<One>() ? "has" : "does not have")
<< " int get()" << endl;
cout << "Two " << (has_get<Two>() ? "has" : "does not have")
<< " int get()" << endl;
cout << "Not " << (has_get<Not>() ? "has" : "does not have")
<< " int get()" << endl;
cout << "One " << (has_add<One>() ? "has" : "does not have")
<< " int add(int, int)" << endl;
cout << "Two " << (has_add<Two>() ? "has" : "does not have")
<< " int add(int, int)" << endl;
cout << "Not " << (has_add<Not>() ? "has" : "does not have")
<< " int add(int, int)" << endl;
cout << "int " << (has_get<int>() ? "has" : "does not have")
<< " int get()" << endl;
}
输出
一个有 int get()
两个有 int get()
Not 没有 int get()
一个有 int add(int, int)
两个有 int add(int, int)
Not 没有 int add(int, int)
int 没有 int get()
更新:我的跳棋
/// Checker for typedef with given name and convertible type
#define TYPEDEF_CHECKER(checker, name) \
template<class C, typename T, typename = void> struct checker : std::false_type {}; \
template<class C, typename T> struct checker<C, T, typename std::enable_if< \
std::is_convertible<typename C::name, T>::value>::type> : std::true_type {}
/// Checker for typedef with given name and exact type
#define TYPEDEF_CHECKER_STRICT(checker, name) \
template<class C, typename T, typename = void> struct checker : std::false_type {}; \
template<class C, typename T> struct checker<C, T, typename std::enable_if< \
std::is_same<typename C::name, T>::value>::type> : std::true_type {}
/// Checker for typedef with given name and any type
#define TYPEDEF_CHECKER_ANY(checker, name) \
template<class C, typename = void> struct checker : std::false_type {}; \
template<class C> struct checker<C, typename std::enable_if< \
!std::is_same<typename C::name*, void>::value>::type> : std::true_type {}
/// Checker for member with given name and convertible type
#define MTYPE_CHECKER(checker, name) \
template<class C, typename T, typename = void> struct checker : std::false_type {}; \
template<class C, typename T> struct checker<C, T, typename std::enable_if< \
std::is_convertible<decltype(C::name), T>::value>::type> : std::true_type {}
/// Checker for member with given name and exact type
#define MTYPE_CHECKER_STRICT(checker, name) \
template<class C, typename T, typename = void> struct checker : std::false_type {}; \
template<class C, typename T> struct checker<C, T, typename std::enable_if< \
std::is_same<decltype(C::name), T>::value>::type> : std::true_type {}
/// Checker for member with given name and any type
#define MTYPE_CHECKER_ANY(checker, name) \
template<class C, typename = void> struct checker : std::false_type {}; \
template<class C> struct checker<C, typename std::enable_if< \
!std::is_same<decltype(C::name)*, void>::value>::type> : std::true_type {}
/// Checker for static const variable with given name and value
#define MVALUE_CHECKER(checker, name, val) \
template<class C, typename = void> struct checker : std::false_type {}; \
template<class C> struct checker<C, typename std::enable_if< \
std::is_convertible<decltype(C::name), const decltype(val)>::value && C::name == val>::type> : std::true_type {}
/// Checker for static const variable with given name, value and type
#define MVALUE_CHECKER_STRICT(checker, name, val) \
template<class C, typename = void> struct checker : std::false_type {}; \
template<class C> struct checker<C, typename std::enable_if< \
std::is_same<decltype(C::name), const decltype(val)>::value && C::name == val>::type> : std::true_type {}
/// Checker for member function with convertible return type and accepting given arguments
#define METHOD_CHECKER(checker, name, ret, args) \
template<class C, typename=void> struct checker : std::false_type {}; \
template<class C> struct checker<C, typename std::enable_if< \
std::is_convertible<decltype(std::declval<C>().name args), ret>::value>::type> : std::true_type {};
/// Checker for member function with exact retutn type and accepting given arguments
#define METHOD_CHECKER_STRICT_RET(name, fn, ret, args) \
template<class C, typename=void> struct name : std::false_type {}; \
template<class C> struct name<C, typename std::enable_if< \
std::is_same<decltype(std::declval<C>().fn args), ret>::value>::type> : std::true_type {};
/// Checker for member function accepting given arguments
#define METHOD_CHECKER_ANY(name, fn, args) \
template<class C, typename=void> struct name : std::false_type {}; \
template<class C> struct name<C, typename std::enable_if< \
!std::is_same<decltype(std::declval<C>().fn args)*, void>::value>::type> : std::true_type {};
测试代码
struct One {
typedef int type;
static constexpr bool v = true;
type x;
One(type x = 0): x(x) {}
~One() {}
type get() { return x; }
type add(type x, type y) { return x+y; }
};
struct Two: One {};
struct Not {};
TYPEDEF_CHECKER(has_type, type);
TYPEDEF_CHECKER_ANY(any_type, type);
TYPEDEF_CHECKER_STRICT(exact_type, type);
MTYPE_CHECKER(has_x, x);
MTYPE_CHECKER_ANY(any_x, x);
MTYPE_CHECKER_STRICT(exact_x, x);
MVALUE_CHECKER(true_v, v, true);
MVALUE_CHECKER(true_z, z, true);
MVALUE_CHECKER(false_v, v, false);
MVALUE_CHECKER(one_v, v, 1);
MVALUE_CHECKER_STRICT(exact_v, v, 1);
METHOD_CHECKER(has_get, get, long, ());
METHOD_CHECKER(has_add, add, long, (1,2))
METHOD_CHECKER_ANY(any_get, get, ());
METHOD_CHECKER_STRICT_RET(int_get, get, int, ())
METHOD_CHECKER_STRICT_RET(long_get, get, long, ())
int main() {
#define CHECK(name, desc, ...) cout << endl; \
cout << "One " << (name<One, ##__VA_ARGS__>() ? "has " : "does not have ") << desc << endl; \
cout << "Two " << (name<Two, ##__VA_ARGS__>() ? "has " : "does not have ") << desc << endl; \
cout << "Not " << (name<Not, ##__VA_ARGS__>() ? "has " : "does not have ") << desc << endl; \
cout << "int " << (name<int, ##__VA_ARGS__>() ? "has " : "does not have ") << desc << endl
string sep = string(60, '-');
cout << sep;
CHECK(any_type, "typedef type");
CHECK(has_type, "typedef type convertible to long", long);
CHECK(exact_type, "typedef type = int", int);
CHECK(exact_type, "typedef type = long", long);
cout << sep;
CHECK(any_x, "var x");
CHECK(has_x, "var x of type convertible to long", long);
CHECK(exact_x, "var x of type int", int);
CHECK(exact_x, "var x of type long", long);
cout << sep;
CHECK(true_v, "var v with value equal to true");
CHECK(true_z, "var z with value equal to true");
CHECK(false_v, "var v with value equal to false");
CHECK(one_v, "var v with value equal to 1");
CHECK(exact_v, "var v with value equal to 1 of type int");
cout << sep;
CHECK(has_get, "get()");
CHECK(has_get, "get() with return type covertible to long");
CHECK(has_add, "add() accepting two ints and returning ~ long");
CHECK(int_get, "int get()");
CHECK(long_get, "long get()");
}
输出
一个有 typedef 类型
两个有typedef类型
Not 没有 typedef 类型
int 没有 typedef 类型
一个具有可转换为 long 的 typedef 类型
两个有 typedef 类型可转换为 long
Not 没有可转换为 long 的 typedef 类型
int 没有可转换为 long 的 typedef 类型
一个有 typedef type = int
两个有 typedef type = int
Not 没有 typedef type = int
int 没有 typedef type = int
一个没有 typedef type = long
二没有typedef type = long
Not 没有 typedef type = long
int 没有 typedef type = long
-------------------------------------------------- ----------
一个有 var x
两个有 var x
Not 没有 var x
int 没有 var x
一个具有可转换为 long 类型的 var x
两个具有可转换为 long 类型的 var x
Not 没有可转换为 long 类型的 var x
int 没有可转换为 long 类型的 var x
一个具有 int 类型的 var x
两个具有 int 类型的 var x
Not 没有 int 类型的 var x
int 没有 int 类型的 var x
一个没有 long 类型的 var x
两个没有 long 类型的 var x
Not 没有 long 类型的 var x
int 没有 long 类型的 var x
-------------------------------------------------- ----------
一个 var v 的值等于 true
两个具有 var v 的值等于 true
Not 没有值等于 true 的 var v
int 没有值等于 true 的 var v
一个没有值等于 true 的 var z
两个没有值等于 true 的 var z
Not 没有值等于 true 的 var z
int 没有值等于 true 的 var z
一个没有 var v 的值等于 false
两个没有 var v 的值等于 false
Not 没有值等于 false 的 var v
int 没有值等于 false 的 var v
一个具有 var v 的值等于 1
两个具有 var v 的值等于 1
Not 没有值等于 1 的 var v
int 没有值等于 1 的 var v
一个没有 var v 的值等于 1 的 int 类型
两个没有 var v 值等于 1 的 int 类型
Not 没有值等于 1 的 int 类型的 var v
int 没有值等于 1 的 int 类型的 var v
-------------------------------------------------- ----------
一个有 get()
二有get()
Not 没有 get()
int 没有 get()
一个具有 get() 的返回类型可转换为 long
两个具有 get() 的返回类型可转换为 long
Not 没有返回类型可转换为 long 的 get()
int 没有返回类型可转换为 long 的 get()
一个 add() 接受两个整数并返回 ~ long
两个 add() 接受两个整数并返回 ~ long
Not 没有 add() 接受两个整数并返回 ~ long
int 没有 add() 接受两个整数并返回 ~ long
一个有 int get()
两个有 int get()
Not 没有 int get()
int 没有 int get()
一不长 get()
二不长get()
not 没有长 get()
int 没有长 get()