使用模板在 class 中设置函数类型会出错

Using Templates to set function types in a class gives error

所以我有这个 class:

 template <typename callBackOne,
           typename callBackTwo>
class MyClass {       // The class
  public: 
    callBackOne cbo;
    callBackTwo cbt;           
    MyClass(callBackOne cbop, callBackTwo cbtp){
      cbop();
      cbtp();
    }
};

它所做的只是调用您在其构造函数参数中提供的函数。 回调函数类型由模板推导出来。我无法以任何其他方式做到这一点。 为什么我尝试时出错:

MyClass<void,void> test(voidFuncOne,voidFuncTwo);

错误:

error: invalid parameter type ‘void’
no matching function for call to ‘MyClass<void, void>::MyClass(int (&)(), void (&)())’

24 | MyClass testy(test,testTwo);

我尝试了很多不同的东西,包括:

MyClass<void(&)(),void(&)()> test(test,testTwo);
MyClass<void,void> test(&test,&testTwo);
MyClass<void (*)(void),void (*)(void)> test(test,testTwo);

我知道可以像这样将函数作为参数传递,但我不知道该怎么做。是语文知识的问题。

Class 成员 cbocbt 似乎没用:它们没有在 MyClass 的构造函数中分配,根本没有使用。

如果想保存函数指针供以后使用,可以在<functional>中尝试std::function。这是一个例子:

#include <iostream>
#include <functional>

template <typename callBackOne,  typename callBackTwo>
class MyClass {       // The class
public:
    std::function<callBackOne> cbo;
    std::function<callBackTwo> cbt;

    MyClass(callBackOne cbop, callBackTwo cbtp) : cbo(cbop), cbt(cbtp) {
    }
};

void voidFuncOne() { std::cout << "One\n"; }
void voidFuncTwo() { std::cout << "Two\n"; }

int main()
{
    MyClass<void(), void()> test(voidFuncOne, voidFuncTwo);
    test.cbo();
    test.cbt();
    return 0;
}

模板class的参数类型是void,但是构造函数的参数类型不是void类型,这是错误的根本原因。

尝试以下操作:

MyClass<int(), void()> test(voidFuncOne,voidFuncTwo);

MyClass<decltype(voidFuncOne),decltype(voidFuncTwo)> test(voidFuncOne,voidFuncTwo);

问题 是您传递的显式模板参数是 void 类型,但函数参数 voidFuncOnevoidFuncTwo 将隐式转换为 void (*)() 并传递,但由于没有从 void(*)()void 的转换,您会收到上述错误。

C++17

使用 C++17,您可以使用 class template argument deduction(又名 CTAD),如下所示:

template <typename callBackOne,
           typename callBackTwo>
class MyClass {       // The class
  public: 
    callBackOne cbo;
    callBackTwo cbt;           
    MyClass(callBackOne cbop, callBackTwo cbtp){
      cbop();
      cbtp();
    }
};
void voidFuncOne()
{
    std::cout<<"funcone called"<<std::endl;
}
void voidFuncTwo()
{
    std::cout<<"functow called"<<std::endl;
}
MyClass test(voidFuncOne,voidFuncTwo); //CTAD used automatically here
//-----^------------------------------->no need to pass arguments explicitly since CTAD will be used

Demo

Pre-C++17

在这里您可以显式指定模板参数为 void(*)() 类型,如下所示:

template <typename callBackOne,
           typename callBackTwo>
class MyClass {       // The class
  public: 
    callBackOne cbo;
    callBackTwo cbt;           
    MyClass(callBackOne cbop, callBackTwo cbtp){
      cbop();
      cbtp();
    }
};
void voidFuncOne()
{
    std::cout<<"funcone called"<<std::endl;
}
void voidFuncTwo()
{
    std::cout<<"functow called"<<std::endl;
}

//------vvvvvvvvv--vvvvvvvvv--------------------------------->template arguments changed from void to void(*)()
MyClass<void(*)(), void(*)()> test(voidFuncOne,voidFuncTwo);

Demo