@@ -19,6 +19,7 @@ namespace impl
1919template<class T, bool C>
2020struct is_const_helper : bool_constant<C>
2121{
22+ using type = T;
2223 NBL_CONSTEXPR_STATIC_INLINE bool is_constant = is_const<T>::value;
2324};
2425
@@ -33,6 +34,11 @@ enum e_member_presence
3334template<class T>
3435T declval (){}
3536
37+ template<bool =false >
38+ struct if_2_else_1 : integral_constant<uint32_t,1 > {};
39+ template<>
40+ struct if_2_else_1<true > : integral_constant<uint32_t,2 > {};
41+
3642}
3743
3844typedef impl::e_member_presence e_member_presence;
@@ -67,5 +73,94 @@ NBL_GENERATE_MEMBER_TESTER(y)
6773NBL_GENERATE_MEMBER_TESTER (z)
6874NBL_GENERATE_MEMBER_TESTER (w)
6975
76+
77+ // Even though it should work for some reason tests fail
78+ // proof it works : https://godbolt.org/z/EzPWGnTPb
79+
80+ #define CAT (x, y) x##y
81+ #define TYPE_DECLARE (n) typename Arg##n
82+ #define TYPE_DECLARE_DEFAULT (n) TYPE_DECLARE (n)=void
83+ #define TYPE_FWD (n) Arg##n
84+ #define DECLVAL_DECLARE (n) impl::declval<Arg##n>()
85+
86+ #define FOR_EACH0 (fn)
87+ #define FOR_EACH1 (fn) fn (1 )
88+ #define FOR_EACH2 (fn) fn (2 ), FOR_EACH1 (fn)
89+ #define FOR_EACH3 (fn) fn (3 ), FOR_EACH2 (fn)
90+ #define FOR_EACH4 (fn) fn (4 ), FOR_EACH3 (fn)
91+ #define FOR_EACH (fn, n) CAT (FOR_EACH, n)(fn)
92+
93+ #define GENERATE_STATIC_METHOD_TESTER_SPEC0 (x) \
94+ template<class T> \
95+ struct has_static_method_##x<T, typename make_void<decltype (T::x ())>::type> : true_type \
96+ { \
97+ using return_type = decltype (T::x ()); \
98+ NBL_CONSTEXPR_STATIC_INLINE uint arg_count = 0 ; \
99+ };
100+
101+ #define GENERATE_STATIC_METHOD_TESTER_SPEC (x, n) \
102+ template<class T, FOR_EACH (TYPE_DECLARE, n)> \
103+ struct has_static_method_##x<T, FOR_EACH (TYPE_FWD, n), typename make_void<decltype (T::x (FOR_EACH (DECLVAL_DECLARE, n)))>::type> : true_type \
104+ { \
105+ using return_type = decltype (T::x (FOR_EACH (DECLVAL_DECLARE, n))); \
106+ NBL_CONSTEXPR_STATIC_INLINE uint arg_count = n; \
107+ };
108+
109+ #define GENERATE_STATIC_METHOD_TESTER (x) \
110+ template<typename T, FOR_EACH (TYPE_DECLARE_DEFAULT, 4 ), class =void > \
111+ struct has_static_method_##x : false_type {}; \
112+ GENERATE_STATIC_METHOD_TESTER_SPEC0 (x) \
113+ GENERATE_STATIC_METHOD_TESTER_SPEC (x, 1 ) \
114+ GENERATE_STATIC_METHOD_TESTER_SPEC (x, 2 ) \
115+ GENERATE_STATIC_METHOD_TESTER_SPEC (x, 3 ) \
116+ GENERATE_STATIC_METHOD_TESTER_SPEC (x, 4 )
117+
118+ #define GENERATE_METHOD_TESTER_SPEC0 (x) \
119+ template<class T> \
120+ struct has_method_##x<T, typename make_void<decltype (impl::declval<T>().x ())>::type> : impl::if_2_else_1<impl::has_static_method_##x<T>::value> \
121+ { \
122+ using return_type = decltype (impl::declval<T>().x ()); \
123+ NBL_CONSTEXPR_STATIC_INLINE uint arg_count = 0 ; \
124+ };
125+
126+ #define GENERATE_METHOD_TESTER_SPEC (x, n) \
127+ template<class T, FOR_EACH (TYPE_DECLARE, n)> \
128+ struct has_method_##x<T, FOR_EACH (TYPE_FWD, n), typename make_void<decltype (impl::declval<T>().x (FOR_EACH (DECLVAL_DECLARE, n)))>::type> : impl::if_2_else_1<impl::has_static_method_##x<T,FOR_EACH (TYPE_FWD, n)>::value> \
129+ { \
130+ using return_type = decltype (impl::declval<T>().x (FOR_EACH (DECLVAL_DECLARE, n))); \
131+ NBL_CONSTEXPR_STATIC_INLINE uint arg_count = n; \
132+ };
133+
134+ /*
135+ types that are impilicitly convertible to each other mess this check up
136+
137+ struct S
138+ {
139+ void a(int) { return 0;}
140+ };
141+
142+ has_method_a<S, float>::value will be true
143+ since float is implicitly convertible to int and
144+ due to how we check function signatures at the moment
145+ */
146+
147+ #define GENERATE_METHOD_TESTER (x) \
148+ namespace nbl { \
149+ namespace hlsl { \
150+ namespace impl { GENERATE_STATIC_METHOD_TESTER (x) } \
151+ template<typename T, FOR_EACH (TYPE_DECLARE_DEFAULT, 4 ), class =void > \
152+ struct has_method_##x : false_type {}; \
153+ GENERATE_METHOD_TESTER_SPEC0 (x) \
154+ GENERATE_METHOD_TESTER_SPEC (x, 1 ) \
155+ GENERATE_METHOD_TESTER_SPEC (x, 2 ) \
156+ GENERATE_METHOD_TESTER_SPEC (x, 3 ) \
157+ GENERATE_METHOD_TESTER_SPEC (x, 4 ) \
158+ }}
159+
160+
161+ GENERATE_METHOD_TESTER (a)
162+ GENERATE_METHOD_TESTER (b)
163+
164+
70165#endif
71166#endif
0 commit comments