1 | #ifndef MemberFunctionCheckerH
|
---|
2 | #define MemberFunctionCheckerH
|
---|
3 | /*-------------------------------------------------------------------------------------------------------------------------------------------
|
---|
4 | MemberFunctionChecker.hpp
|
---|
5 | from http://groups.google.com/group/comp.lang.c++.moderated/tree/browse_frm/thread/4f7c7a96f9afbe44/c95a7b4c645e449f#doc_e5fbc9305539f699
|
---|
6 | --------------------------------------------------------------------------------------------------------------------------------------------*/
|
---|
7 |
|
---|
8 |
|
---|
9 | namespace MemberFunctionChecker {
|
---|
10 |
|
---|
11 | template <typename Type>
|
---|
12 | class has_member {
|
---|
13 | class yes { char m;};
|
---|
14 | class no { yes m[2];};
|
---|
15 | struct BaseMixin { void operator()() {} };
|
---|
16 | struct Base : public Type, public BaseMixin {};
|
---|
17 | template <typename T, T t> class Helper {};
|
---|
18 | template <typename U>
|
---|
19 | static no deduce(U*, Helper<void (BaseMixin::*)(), &U::operator()>* = 0);
|
---|
20 | static yes deduce(...);
|
---|
21 | public:
|
---|
22 | static const bool result = sizeof(yes) == sizeof(deduce((Base*)(0)));
|
---|
23 | };
|
---|
24 |
|
---|
25 | namespace details {
|
---|
26 | template <typename type> class void_exp_result {};
|
---|
27 | template <typename type, typename U> U const& operator,(U const&, void_exp_result<type>);
|
---|
28 | template <typename type, typename U> U& operator,(U&, void_exp_result<type>);
|
---|
29 | template <typename src_type, typename dest_type>
|
---|
30 | struct clone_constness {
|
---|
31 | typedef dest_type type;
|
---|
32 | };
|
---|
33 | template <typename src_type, typename dest_type>
|
---|
34 | struct clone_constness<const src_type, dest_type> {
|
---|
35 | typedef const dest_type type;
|
---|
36 | };
|
---|
37 | }
|
---|
38 |
|
---|
39 | template <typename type, typename call_details>
|
---|
40 | struct is_call_possible {
|
---|
41 | private:
|
---|
42 | class yes {};
|
---|
43 | class no { yes m[2]; };
|
---|
44 | struct derived : public type {
|
---|
45 | using type::operator();
|
---|
46 | no operator()(...) const;
|
---|
47 | };
|
---|
48 | typedef typename details::clone_constness<type, derived>::type derived_type;
|
---|
49 | template <typename T, typename due_type>
|
---|
50 | struct return_value_check {
|
---|
51 | static yes deduce(due_type);
|
---|
52 | static no deduce(...);
|
---|
53 | };
|
---|
54 | template <typename T>
|
---|
55 | struct return_value_check<T, void> {
|
---|
56 | static yes deduce(details::void_exp_result<type>);
|
---|
57 | static no deduce(...);
|
---|
58 | };
|
---|
59 |
|
---|
60 | template <bool has, typename F>
|
---|
61 | struct impl { static const bool value = false; };
|
---|
62 | template <typename arg1, typename r>
|
---|
63 | struct impl<true, r(arg1)> {
|
---|
64 | static const bool value =
|
---|
65 | sizeof(
|
---|
66 | return_value_check<type, r>::deduce((
|
---|
67 | ((derived_type*)0)->operator()(*(arg1*)0),
|
---|
68 | details::void_exp_result<type>()))
|
---|
69 | ) == sizeof(yes);
|
---|
70 | };
|
---|
71 | template <typename arg1, typename arg2, typename r>
|
---|
72 | struct impl<true, r(arg1, arg2)> {
|
---|
73 | static const bool value =
|
---|
74 | sizeof(
|
---|
75 | return_value_check<type, r>::deduce((
|
---|
76 | ((derived_type*)0)->operator()(*(arg1*)0, *(arg2*)0),
|
---|
77 | details::void_exp_result<type>()))
|
---|
78 | ) == sizeof(yes);
|
---|
79 | };
|
---|
80 | template <typename arg1, typename arg2, typename arg3, typename r>
|
---|
81 | struct impl<true, r(arg1, arg2, arg3)> {
|
---|
82 | static const bool value =
|
---|
83 | sizeof(
|
---|
84 | return_value_check<type, r>::deduce(
|
---|
85 | (((derived_type*)0)->operator()(*(arg1*)0, *(arg2*)0, *(arg3*)0),
|
---|
86 | details::void_exp_result<type>()))
|
---|
87 | ) == sizeof(yes);
|
---|
88 | };
|
---|
89 | public:
|
---|
90 | static const bool value = impl<has_member<type>::result, call_details>::value;
|
---|
91 | };
|
---|
92 |
|
---|
93 | }
|
---|
94 | #endif
|
---|