1: // 判断类是否含有foo这个成员变量和成员函数
2: // 针对GCC的实现,基本上就是针对标准C++的实现
3: #ifdef __GNUC__
4:
5: // check_property_foo函数的两个重载版本,结合decltype,
6: // 通过SFINAE在编译期推导指定类型是否含有foo这个成员变量
7: char check_property_foo(...);
8:
9: template <typename T>
10: void* check_property_foo(T const& t, decltype(&(t.foo)) p = 0);
11:
12: // 这个类模板通过check_property_foo得出T是否含有foo这个成员变量
13: template <typename T>
14: struct has_property_foo : public std::integral_constant<
15: bool, sizeof(check_property_foo(*static_cast(0))) == sizeof(void*)>
16: {
17: };
18:
19: // check_method_foo函数的两个重载版本,结合decltype,
20: // 通过SFINAE在编译期推导指定类型是否含有foo这个成员函数
21: char check_method_foo(...);
22:
23: template <typename T>
24: void* check_method_foo(T const& t, decltype(&(T::foo)) p = 0);
25:
26: // 这个类模板通过check_method_foo得出T是否含有foo这个成员函数
27: template <typename T>
28: struct has_method_foo : public std::integral_constant<
29: bool, !has_property_foo::value &&
30: sizeof(check_method_foo(*static_cast(0))) == sizeof(void*)>
31: {
32: };
33: #endif
34:
35: // 针对VC的实现,由于VC编译器在处理decltype和SFINAE情况下存在bug,
36: // 我们只能采用一些花招来绕过这个bug
37: #ifdef _MSC_VER
38:
39: // check_member_foo函数的两个重载版本,结合decltype,
40: // 通过SFINAE在编译期推导指定类型是否含有foo这个成员变量或函数
41: char check_member_foo(...);
42:
43: template <typename T>
44: auto check_member_foo(T const& t, decltype(&(t.foo)) p = 0)->decltype(p);
45:
46: // 这个类模板通过check_member_foo得出T是否含有foo这个成员变量
47: template <typename T>
48: struct has_property_foo
49: {
50: static const bool value =
51: sizeof(check_member_foo(*static_cast(0))) != sizeof(char) &&
52: std::is_pointerstatic_cast(0)))>::value;
53: };
54:
55: // 这个类模板通过check_member_foo得出T是否含有foo这个成员函数
56: template <typename T>
57: struct has_method_foo
58: {
59: static const bool value =
60: sizeof(check_member_foo(*static_cast(0))) != sizeof(char) &&
61: !std::is_pointerstatic_cast(0)))>::value;
62: };
63:
64: #endif
65:
66: // 先定义几个类供实现检测
67: struct WithPropertyFoo
68: {
69: int foo;
70: };
71:
72: struct WithMethodFoo
73: {
74: void foo();
75: };
76:
77: struct WithRefPorpertyFoo
78: {
79: int& foo;
80: };
81:
82: struct WithoutFoo
83: {
84: void bar();
85: };
86:
87: // 用static_assert对这些条件进行检查
88: static_assert(has_property_foo::value, "property foo needed");
89: static_assert(has_method_foo::value, "method foo needed");
90: static_assert(!has_property_foo::value, "no property foo");
91: static_assert(!has_method_foo::value, "no methoed foo");
92: static_assert(has_property_foo::value, "property foo needed");
93: static_assert(!has_method_foo::value, "no method foo");