std: любой вызывающий исключение тип функции разрешения - PullRequest
1 голос
/ 04 июня 2019

Я столкнулся с проблемой при разрешении типа функции из std :: any.

Я в основном обертываю функцию и ее начальные аргументы в лямбда-функцию и вызываю ее позже, чтобы вызвать обернутую функцию, но с новым набором аргументов. Вот так выглядит упакованная функция.

void Hello(std::string str)
{
    LOG(str);
}

И я пытаюсь выполнить лямбда-оболочку следующим образом: у меня есть лямбда-функция, которая либо выполняет упакованные функции, и / или иным образом просто возвращает упакованную функцию.

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;
                                                });
}

Теперь, когда я пытаюсь вызвать эту лямбу так:

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 Ответ

1 голос
/ 04 июня 2019

Во-первых, если вам не нужно использовать аргументы, предоставленные в MMM, и переопределить их, это скрывает ошибку, когда вы отправляете неправильные аргументы в MMM.Я бы предложил предоставить требуемый материал для MMM, чтобы он мог создать правильный набор аргументов.


Ваши функции MMM и AAA оба получают функцию путем пересылки ссылки.Для правильного разрешения вызова он разрешается в void(&)(std::string), который является ссылкой на функцию.

Затем вы возвращаете эту функцию в своей лямбде:

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) { /* ... */ }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...