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

check function passed to template has class in arguments

这有点难以解释, 在我的 class 中,我有一个带有指针和参数的创建函数 我希望能够检查传递给该函数的函数是否将 ClassPointer 作为其第一个参数,如果是这样,则自动将其添加到 "create" 内的函数中,如果不只是添加普通函数参数,就像我做的那样

       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);

我相信 std::is_same 可能对您有用,正如上一个问题

问题可以更一般化。您可以询问如何确定函数的第 N 个参数是否属于给定类型。要静态获得此问题的答案,您可以创建 SFINAE 辅助结构 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