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

Popular posts from this blog

gridview - Yii2 DataPorivider $totalSum for a column -

java - Suppress Jboss version details from HTTP error response -

Sass watch command compiles .scss files before full sftp upload -