从std :: any解析函数类型时遇到问题。
我基本上是将一个函数及其初始参数包装在一个lambda函数中,稍后再调用它来调用被包装的函数,但带有一组新的参数。这就是包装函数的样子。
void Hello(std::string str)
{
LOG(str);
}
我正在尝试像这样完成包装器lambda:我有一个lambda函数,它可以执行包装的函数,和/或以其他方式简单地返回包装的函数。
template<typename FuncName, typename... FuncArgs>
bool MMM(std::string EventName, FuncName&& EventFunction, FuncArgs&&... Args) noexcept
{
//Storing lambda here
auto fPtr = std::function<std::any(bool)>([=](bool x)
{
if(x){
EventFunction(Args...);
}
return (FuncName)EventFunction;
});
}
现在,当我尝试像这样调用此lamdba时:
template<typename E, typename FuncName, typename... FuncArgs>
bool AAA(E EventName, FuncName &&EventFunction, FuncArgs&&... Args)
{
try {
//resolving lambda and invoking it here
auto func = std::any_cast<decltype(EventFunction)>(fPtr)(false));
func(Args...);
} catch (...) {
std::cout<<"Didn't invoke function: Mismatch argument type.\n";
}
return true;
}
我通过以下方式调用此函数:
MMM(e, Hello, "Hello Florida");
MMM(e, Hello, "Hello USA");
AAA(e, Hello, "Hello World");
问题: 调用函数AAA时,出现异常,提示auto_cast无法解析函数类型。
在运行时,我看到(fPtr)(false)返回:
std::__1::function<std::__1::any (bool)> Function = Hello(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >)
而decltype(EventFunction)的类型似乎是
void (&)(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >) 0x0000000100012540
这似乎使我几乎接近存储在里面的std :: any,但是仍然错过了我不明白的东西!如何解决此std :: any_cast不匹配?
答案 0 :(得分:1)
首先,如果不需要使用MMM
中提供的参数并覆盖它们,则会在向MMM
发送错误的参数时隐藏一个错误。我建议向MMM
提供所需的内容,以便可以制定正确的参数集。
您的函数MMM
和AAA
都通过转发引用来接收该函数。为了使调用正确解析,它解析为void(&)(std::string)
,这是对函数的引用。
然后,您在lambda中返回该函数:
return (FuncName)EventFunction;
这确实会将EventFunction
转换回函数引用,但是返回类型推导将衰减该类型,因此它等效于此:
[](bool) -> void(*)(std::string) { /* ... */ }
然后,您的其他函数执行相同的操作。如果我们扩展模板,我们将得到如下内容:
auto func = std::any_cast<void(&)(std::string)>(fPtr)(false));
func(Args...);
但是std::any
中包含的类型是指向函数的指针,而不是引用。
即使我们修复了返回类型,std::any
也会衰减引用以使其始终成为函数指针。
解决方案是不通过转发引用来接收该功能,因为无论如何您都不会转发它:
template<typename E, typename FuncName, typename... FuncArgs>
bool MMM(E EventName, FuncName EventFunction, FuncArgs&&... Args) { /* ... */ }
template<typename E, typename FuncName, typename... FuncArgs>
bool AAA(E EventName, FuncName EventFunction, FuncArgs&&... Args) { /* ... */ }