将模板化参数包传递给回调函数(也是模板化函数)
Pass templated parameter pack to callback function (also a templated function)
目前在我的代码中我有一个函数,它接受各种参数和一个回调对象(它是一个简单的 class 的实例,带有一个 Callback(void) 函数)。这现在工作得很好,但它使代码混乱,因为我有很多这样的 classes,并且在其中大多数中,它们的变量仅由 Callback() 函数使用。
我想用像这样的简单函数替换 classes:
#include <iostream>
#include <string>
template<class T>
class TestClass {
public:
template<typename ...TArgs>
using CallbackFuncType = bool(T &Data, TArgs && ...Args);
TestClass(const T &Data) : data(Data) {}
template<typename ...TArgs>
bool Function(
CallbackFuncType<TArgs...> Callback,
TArgs && ...Args
)
{
return Callback(data,
std::forward<TArgs>(Args)...);
}
private:
const T data;
};
struct DataType {
int valInt;
double valFloat;
std::string ToString()
{
return std::string(
"valInt: " + std::to_string(valInt) +
"valFloat: " + std::to_string(valFloat)
);
}
};
bool CBFunction1(DataType &Data, int Arg0, const std::string &Arg1)
{
std::cout << "Data :" << Data.ToString() << std::endl;
std::cout << "CBFunction1: " <<
"Arg0 : " << Arg0 <<
"Arg1: " << Arg1 <<
std::endl;
return true;
}
bool CBFunction2(DataType &Data, int Arg0, double Arg1, const std::string &Arg2)
{
std::cout << "Data :" << Data.ToString() << std::endl;
std::cout << "CBFunction2: " <<
"Arg0 : " << Arg0 <<
"Arg1: " << Arg0 <<
"Arg2: " << Arg2 <<
std::endl;
return true;
}
int main()
{
DataType data;
data.valInt = 1;
data.valFloat = 1.2;
TestClass<DataType> testObj(data);
std::cout << "test" << std::endl;
std::cout << "call CBFunction1" << std::endl;
bool val1 = testObj.Function(CBFunction1, 11, "test_string");
bool val2 = testObj.Function(CBFunction2, 11, 111.111, "test_string");
return 0;
}
编译后出现以下错误:
1>main.cpp
1>main.cpp(75,24): error C2672: 'TestClass<DataType>::Function': no matching overloaded function found
1>main.cpp(75,64): error C2784: 'bool TestClass<DataType>::Function(bool (__cdecl *)(T &,TArgs &&...),TArgs &&...)': could not deduce template argument for 'bool (__cdecl *)(T &,TArgs &&...)' from 'bool (DataType &,int,const std::string &)'
1> with
1> [
1> T=DataType
1> ]
1>main.cpp(13): message : see declaration of 'TestClass<DataType>::Function'
1>main.cpp(76,24): error C2672: 'TestClass<DataType>::Function': no matching overloaded function found
1>main.cpp(76,73): error C2784: 'bool TestClass<DataType>::Function(bool (__cdecl *)(T &,TArgs &&...),TArgs &&...)': could not deduce template argument for 'bool (__cdecl *)(T &,TArgs &&...)' from 'bool (DataType &,int,double,const std::string &)'
1> with
1> [
1> T=DataType
1> ]
1>main.cpp(13): message : see declaration of 'TestClass<DataType>::Function'
我尝试将 type_identity_t 添加到 Args,但没有成功。
template <typename... TArgs>
bool Function(CallbackFuncType<TArgs...> Callback, TArgs&&... Args)
有几个问题,主要的一个是 TArgs
应该在两个地方推导完全相同。
问题
template <typename... TArgs>
using CallbackFuncType = bool(T& Data, TArgs&&... Args);
是它只能匹配参数为(l或r值)引用的函数。
所以像
template <typename... TArgs>
using CallbackFuncType = bool(T&, TArgs...);
template <typename... TArgs, typename... Ts>
bool Function(CallbackFuncType<TArgs...>* Callback, Ts&& ...Args)
{
return Callback(data, std::forward<Ts>(Args)...);
}
会解决问题,但更简单(也更通用)
template <typename Func, typename... Ts>
bool Function(Func Callback, Ts&& ...Args)
{
return Callback(data, std::forward<Ts>(Args)...);
}
目前在我的代码中我有一个函数,它接受各种参数和一个回调对象(它是一个简单的 class 的实例,带有一个 Callback(void) 函数)。这现在工作得很好,但它使代码混乱,因为我有很多这样的 classes,并且在其中大多数中,它们的变量仅由 Callback() 函数使用。
我想用像这样的简单函数替换 classes:
#include <iostream>
#include <string>
template<class T>
class TestClass {
public:
template<typename ...TArgs>
using CallbackFuncType = bool(T &Data, TArgs && ...Args);
TestClass(const T &Data) : data(Data) {}
template<typename ...TArgs>
bool Function(
CallbackFuncType<TArgs...> Callback,
TArgs && ...Args
)
{
return Callback(data,
std::forward<TArgs>(Args)...);
}
private:
const T data;
};
struct DataType {
int valInt;
double valFloat;
std::string ToString()
{
return std::string(
"valInt: " + std::to_string(valInt) +
"valFloat: " + std::to_string(valFloat)
);
}
};
bool CBFunction1(DataType &Data, int Arg0, const std::string &Arg1)
{
std::cout << "Data :" << Data.ToString() << std::endl;
std::cout << "CBFunction1: " <<
"Arg0 : " << Arg0 <<
"Arg1: " << Arg1 <<
std::endl;
return true;
}
bool CBFunction2(DataType &Data, int Arg0, double Arg1, const std::string &Arg2)
{
std::cout << "Data :" << Data.ToString() << std::endl;
std::cout << "CBFunction2: " <<
"Arg0 : " << Arg0 <<
"Arg1: " << Arg0 <<
"Arg2: " << Arg2 <<
std::endl;
return true;
}
int main()
{
DataType data;
data.valInt = 1;
data.valFloat = 1.2;
TestClass<DataType> testObj(data);
std::cout << "test" << std::endl;
std::cout << "call CBFunction1" << std::endl;
bool val1 = testObj.Function(CBFunction1, 11, "test_string");
bool val2 = testObj.Function(CBFunction2, 11, 111.111, "test_string");
return 0;
}
编译后出现以下错误:
1>main.cpp
1>main.cpp(75,24): error C2672: 'TestClass<DataType>::Function': no matching overloaded function found
1>main.cpp(75,64): error C2784: 'bool TestClass<DataType>::Function(bool (__cdecl *)(T &,TArgs &&...),TArgs &&...)': could not deduce template argument for 'bool (__cdecl *)(T &,TArgs &&...)' from 'bool (DataType &,int,const std::string &)'
1> with
1> [
1> T=DataType
1> ]
1>main.cpp(13): message : see declaration of 'TestClass<DataType>::Function'
1>main.cpp(76,24): error C2672: 'TestClass<DataType>::Function': no matching overloaded function found
1>main.cpp(76,73): error C2784: 'bool TestClass<DataType>::Function(bool (__cdecl *)(T &,TArgs &&...),TArgs &&...)': could not deduce template argument for 'bool (__cdecl *)(T &,TArgs &&...)' from 'bool (DataType &,int,double,const std::string &)'
1> with
1> [
1> T=DataType
1> ]
1>main.cpp(13): message : see declaration of 'TestClass<DataType>::Function'
我尝试将 type_identity_t 添加到 Args,但没有成功。
template <typename... TArgs>
bool Function(CallbackFuncType<TArgs...> Callback, TArgs&&... Args)
有几个问题,主要的一个是 TArgs
应该在两个地方推导完全相同。
问题
template <typename... TArgs>
using CallbackFuncType = bool(T& Data, TArgs&&... Args);
是它只能匹配参数为(l或r值)引用的函数。
所以像
template <typename... TArgs>
using CallbackFuncType = bool(T&, TArgs...);
template <typename... TArgs, typename... Ts>
bool Function(CallbackFuncType<TArgs...>* Callback, Ts&& ...Args)
{
return Callback(data, std::forward<Ts>(Args)...);
}
会解决问题,但更简单(也更通用)
template <typename Func, typename... Ts>
bool Function(Func Callback, Ts&& ...Args)
{
return Callback(data, std::forward<Ts>(Args)...);
}