Итак, у меня есть этот класс:
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<void,void> testy(test,testTwo);
Я пробовал много разных вещей, включая:
MyClass<void(&)(),void(&)()> test(test,testTwo);
MyClass<void,void> test(&test,&testTwo);
MyClass<void (*)(void),void (*)(void)> test(test,testTwo);
Я знаю, что можно передавать функции в качестве таких параметров, но я просто не могу понять, как это сделать. Это проблема знания языка.





Члены класса cbo и cbt кажутся бесполезными: они не присваиваются в конструкторе MyClass и вообще не используются.
Если вы хотите сохранить указатели функций для последующего использования, вы можете попробовать std::function в <functional>. Вот пример:
#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;
}
@Aconcagua, вы правы, лучше использовать MyClass<void(*)(), void(*)()> без изменения определения MyClass.
Тип параметра класса шаблона — void, но тип параметра конструктора не является типом void, что и является основной причиной ошибки.
попробуйте следующее:
MyClass<int(), void()> test(voidFuncOne,voidFuncTwo);
или
MyClass<decltype(voidFuncOne),decltype(voidFuncTwo)> test(voidFuncOne,voidFuncTwo);
С вывод аргумента шаблона класса вы могли бы даже просто получить MyClass test(voidFuncOne, voidFuncTwo) — однако, полагаясь на C++ 17.
Да, это очень хорошая реализация (начиная с C++17).
проблема заключается в том, что явные аргументы шаблона, которые вы передаете, имеют тип void, но аргументы функции voidFuncOne и voidFuncTwo будут неявно преобразованы в void (*)() и переданы, но, поскольку нет преобразования из void(*)() в void, вы получите упомянутую ошибку.
В C++17 вы можете использовать вывод аргумента шаблона класса (он же 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
Здесь вы можете явно указать аргументы шаблона типа 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);
std::function— довольно тяжелый зверь — если вы имеете дело только с указателями на функции, ничто не говорит против их прямого использования. Правильно, однако, необходимо использовать список инициализаторов...