std:任何引发异常的函数类型

时间:2019-06-04 14:06:10

标签: c++ c++17

从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不匹配?

1 个答案:

答案 0 :(得分:1)

首先,如果不需要使用MMM中提供的参数并覆盖它们,则会在向MMM发送错误的参数时隐藏一个错误。我建议向MMM提供所需的内容,以便可以制定正确的参数集。


您的函数MMMAAA都通过转发引用来接收该函数。为了使调用正确解析,它解析为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) { /* ... */ }