Jua*_*vid 1 c++ templates function-pointers function-templates c++11
我有以下类,该类有一个名为的方法errorHandler,需要使用多个不同的回调:
class IOPin;
class IOPinHandler
{
IOPinHandler();
virtual ~IOPinHandler();
static bool ptrFun(IOPinHandler&) { return true; };
template<typename T>
bool init(IOPin& obj, const T& param);
template<typename HandlerReturn = void, typename ...Args>
HandlerReturn errorHandler(const GpioStatusCode& code, HandlerReturn(*callback)(IOPinHandler& obj, const Args&...), const Args&... args);
// Added this overload to support passing lambdas as arguments,
// however does not seems to be called
template<typename HandlerReturn = void, typename ...Args>
HandlerReturn errorHandler(const GpioStatusCode& code, const std::function<HandlerReturn(IOPinHandler&, const Args&...)>& callback, Args&... args);
};
Run Code Online (Sandbox Code Playgroud)
我可以使用以下内容:
return errorHandler(GpioStatusCode::wrongArgumentsError, &IOPinHandler::ptrFun);
Run Code Online (Sandbox Code Playgroud)
代码成功编译并按照我的预期运行。
我还可以通过以下方式使用传递 lambda 函数:
auto fix = [](IOPinHandler& obj) -> bool
{
return true;
};
return errorHandler(GpioStatusCode::wrongArgumentsError, static_cast<bool(*)(IOPinHandler&)>(fix));
Run Code Online (Sandbox Code Playgroud)
这样,代码也能成功编译并运行。
但是,如果我将 capture 添加到 lambda 函数,代码将无法编译:
auto fix = [&](IOPinHandler& obj) -> bool
{
return true;
};
return errorHandler(GpioStatusCode::wrongArgumentsError, fix);
Run Code Online (Sandbox Code Playgroud)
我收到以下编译时错误:
error: no matching function for call to 'IOPinHandler::errorHandler(GpioStatusCode, IOPinHandler::init<GpioMode>::<lambda(IOPinHandler&)>&)'
12 | return errorHandler(GpioStatusCode::wrongArgumentsError, fix);
Run Code Online (Sandbox Code Playgroud)
我认为添加:
template<typename HandlerReturn = void, typename ...Args>
HandlerReturn errorHandler(const GpioStatusCode& code, const std::function<HandlerReturn(IOPinHandler&, const Args&...)>& callback, Args&... args);
Run Code Online (Sandbox Code Playgroud)
将匹配模板实例化以接收 lambda 函数作为参数,但事实上我必须在没有捕获的情况下转换 lambda,并且带有捕获的 lambda 也不起作用,这对我来说有点暗示只有第一个定义或“”正在被errorHandler使用调用。
我的推理正确吗?我怎样才能通过这个?
编辑:完整代码。
#include <functional>
class IOPin;
class IOPinHandler
{
public:
template<typename ...T>
IOPinHandler(const T&... args);
virtual ~IOPinHandler();
static bool ptrFun(IOPinHandler&);
template<typename T>
bool init(const T& param);
template<typename HandlerReturn = void, typename ...Args>
HandlerReturn errorHandler(const int& code, HandlerReturn(*callback)(IOPinHandler& obj, const Args&...), const Args&... args);
// Added this overload to support passing lambdas as arguments,
// however does not seems to be called
template<typename HandlerReturn = void, typename ...Args>
HandlerReturn errorHandler(const int& code, const std::function<HandlerReturn(IOPinHandler&, const Args&...)>& callback, Args&... args);
};
template<typename ...T>
IOPinHandler::IOPinHandler(const T&... args)
{
(init(args),...);
}
bool IOPinHandler::ptrFun(IOPinHandler&)
{
return true;
}
template<typename T>
bool IOPinHandler::init(const T& param)
{
// Compiles with no problem
// return errorHandler(1, &IOPinHandler::ptrFun);
// Compiles with no problem
// auto fix = [](IOPinHandler& obj) -> bool
// {
// return true;
// };
// return errorHandler(1, static_cast<bool(*)(IOPinHandler&)>(fix));
// Does not compiles
auto fix = [&](IOPinHandler& obj) -> bool
{
return true;
};
return errorHandler(1, fix);
}
int main(void)
{
IOPinHandler a(1,'c',true);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
如果我理解正确,您不需要任何成员函数重载,甚至不需要std::function.
您可以将Callableas 模板参数设置为模板参数,并让编译器为您推断出它的类型。
template<typename Callable, typename... Args>
auto errorHandler(const GpioStatusCode& code, Callable callback, Args&&... args)
// -> decltype(callback(args...))---> if compiler does not support C++14 or later
{
// if needed within the function body
using HandlerReturn = decltype(callback(args...));
// ... do something
return callback(std::forward<Args>(args)...);
}
Run Code Online (Sandbox Code Playgroud)