c++ - check function passed to template has class in arguments -
this little hard explain, in class have create function takes pointer , arguments want able check if function im passing function has classpointer 1st argument if automaticly add function inside "create" if not add normal functions arguments if any,like im doing
template <typename function, typename... arguments> void someclass::create(hwnd hwnd, function func, arguments&&... args) { // check if function's 1st argument = class pointer std::function<void()> function = std::function<void()>(std::bind(std::forward<function>(func), this, std::forward<arguments>(args)...)); // else std::function<void()> function = std::function<void()>(std::bind(std::forward<function>(func), std::forward<arguments>(args)...)); } void threadproc1(someclass* pthis, hwnd hwnd) { // stuff in here } void threadproc2(hwnd hwnd) { // stuff in here } test.create(hwnd, threadproc1, hwnd); test.create(hwnd, threadproc2, hwnd);
the problem can more generalized. can ask how determine if n-th argument of function of given type. statically gain answer on question create sfinae helper struct nth_param_is follows:
#include <type_traits> #include <functional> #include <iostream> using namespace std; typedef int hwnd; template<int n, class t, class... args> struct nth_template_param_is: false_type { }; template<int n, class t, class first, class... others> struct nth_template_param_is<n, t, first, others...>: nth_template_param_is<n-1, t, others...> { }; template<class t, class first, class... others> struct nth_template_param_is<0, t, first, others...>: is_same<t, first> { }; template<int n, class t, class foo> struct nth_param_is: false_type {}; template<int n, class t, class result, class... args> struct nth_param_is<n, t, result(*)(args...)>: nth_template_param_is<n, t, args...> { }; struct someclass { template <typename function, typename... arguments> typename enable_if<nth_param_is<0, someclass *, function>::value >::type create(hwnd hwnd, function func, arguments&&... args) { // check if function's 1st argument = class pointer std::function<void()> function = std::function<void()>(std::bind(std::forward<function>(func), this, std::forward<arguments>(args)...)); cout << "function 1st argument = class pointer" << endl; function(); } template <typename function, typename... arguments> typename enable_if<!nth_param_is<0, someclass *, function>::value >::type create(hwnd hwnd, function func, arguments&&... args) { // else cout << "function 1st argument = non-class pointer" << endl; std::function<void()> function = std::function<void()>(std::bind(std::forward<function>(func), std::forward<arguments>(args)...)); function(); } }; void threadproc1(someclass* pthis, hwnd hwnd) { cout << "threadproc1 invoked" << endl; // stuff in here } void threadproc2(hwnd hwnd) { cout << "threadproc2 invoked" << endl; // stuff in here } int main() { hwnd hwnd; someclass test; test.create(hwnd, threadproc1, hwnd); test.create(hwnd, threadproc2, hwnd); }
edit:
i moved functionality between header files , works fine.
example:
my_traits.h:
#ifndef my_traits_h #define my_traits_h #include <type_traits> template<int n, class t, class... args> struct nth_template_param_is: std::false_type { }; template<int n, class t, class first, class... others> struct nth_template_param_is<n, t, first, others...>: nth_template_param_is<n-1, t, others...> { }; template<class t, class first, class... others> struct nth_template_param_is<0, t, first, others...>: std::is_same<t, first> { }; template<int n, class t, class foo> struct nth_param_is: std::false_type {}; template<int n, class t, class result, class... args> struct nth_param_is<n, t, result(*)(args...)>: nth_template_param_is<n, t, args...> { }; #endif
some_class.h:
#ifndef some_class_h #define some_class_h #include <type_traits> #include <iostream> #include <functional> #include "my_traits.h" typedef int hwnd; struct someclass { // check if function's 1st argument = class pointer template <typename function, typename... arguments> typename std::enable_if<nth_param_is<0, someclass *, function>::value >::type create(hwnd hwnd, function func, arguments&&... args) { std::function<void()> function = std::function<void()>(std::bind(std::forward<function>(func), this, std::forward<arguments>(args)...)); std::cout << "function 1st argument = class pointer" << std::endl; function(); } template <typename function, typename... arguments> typename std::enable_if<!nth_param_is<0, someclass *, function>::value >::type create(hwnd hwnd, function func, arguments&&... args) { std::cout << "function 1st argument = non-class pointer" << std::endl; std::function<void()> function = std::function<void()>(std::bind(std::forward<function>(func), std::forward<arguments>(args)...)); function(); } }; #endif
usage.cc:
#include <iostream> #include "some_class.h" void threadproc1(someclass* pthis, hwnd hwnd) { std::cout << "threadproc1 invoked" << std::endl; // stuff in here } void threadproc2(hwnd hwnd) { std::cout << "threadproc2 invoked" << std::endl; // stuff in here } void threadproc3(someclass* pthis, int arg1, int arg2) { std::cout << "threadproc3 invoked" << std::endl; // stuff in here } int main() { hwnd hwnd; someclass test; test.create(hwnd, threadproc1, hwnd); test.create(hwnd, threadproc2, hwnd); test.create(hwnd, threadproc3, 1, 2); }
compilation:
g++ -std=c++11 usage.cc
usage:
./a.out
output:
function 1st argument = class pointer threadproc1 invoked function 1st argument = non-class pointer threadproc2 invoked function 1st argument = class pointer threadproc3 invoked
Comments
Post a Comment