传递给模板的check函数在参数中有class

时间:2016-02-27 16:12:37

标签: c++ c++11 sfinae

这有点难以解释, 在我的类中,我有一个带有指针和参数的create函数 我希望能够检查传递给该函数的函数是否具有ClassPointer作为其第一个参数,如果这样自动将其添加到函数内部" create"如果不是只是添加正常的函数参数(如果有的话),比如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)
        {
             // do some stuff in here
        }

        void ThreadProc2(HWND hwnd)
        {
             // do some stuff in here
        }

test.Create(hwnd, ThreadProc1, hwnd);
test.Create(hwnd, ThreadProc2, hwnd);

2 个答案:

答案 0 :(得分:1)

问题可以更加普遍。您可以询问如何确定函数的第N个参数是否属于给定类型。要在这个问题上静态获得答案,您可以创建SFINAE helper struct nth_param_is,如下所示:

#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 with 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 with 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;
             // do some stuff in here
        }

        void ThreadProc2(HWND hwnd)
        {

             cout << "ThreadProc2 invoked" << endl;
             // do some stuff in here
        }



int main() {
HWND hwnd;
SomeClass test;
test.create(hwnd, ThreadProc1, hwnd);
test.create(hwnd, ThreadProc2, hwnd);
}

修改

我在头文件之间移动了功能,一切正常 例如:

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 with 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 with 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;
     // do some stuff in here
}
void ThreadProc2(HWND hwnd) {    
     std::cout << "ThreadProc2 invoked" << std::endl;
     // do some stuff in here
}

void ThreadProc3(SomeClass* pThis, int arg1, int arg2) {
     std::cout << "ThreadProc3 invoked" << std::endl;
     // do some 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);
}

汇编:

g++ -std=c++11 usage.cc

用法:

./a.out

输出:

function with 1st argument = class pointer
ThreadProc1 invoked
function with 1st argument = non-class pointer
ThreadProc2 invoked
function with 1st argument = class pointer
ThreadProc3 invoked

答案 1 :(得分:0)

我相信std :: is_same可能对你有用https://jsfiddle.net/pz1yd11u/1/