包装模板回调?

Mat*_*nti 2 c++ lambda templates auto generic-lambda

立即回调

请考虑以下示例:

template <typename lambda> void call_me_back(const lambda & callback)
{
    // Very complicated calculation to find the meaning of everything

    callback(42);
}

int main()
{
    call_me_back([](const int & value)
    {
        std :: cout << value << std :: endl;
    });
}
Run Code Online (Sandbox Code Playgroud)

在这里,我提供call_me_back了一个接受一个的lambda int.经过一些长时间的计算后call_me_back调用callback,并callback打印出来.像蛋糕一样容易.

现在,根据执行情况,call_me_back需要callback使用int或使用其他类型调用.我们可以编辑前面的例子

template <typename lambda> void call_me_back(const lambda & callback)
{
    // Very complicated calculation to find the meaning of everything

    if(rand() % 2)
        callback(42);
    else
        callback("Kill all the humans.");
}

int main()
{
    call_me_back([](const auto & value)
    {
        std :: cout << value << std :: endl;
    });
}
Run Code Online (Sandbox Code Playgroud)

到现在为止还挺好.现在callback可以value根据其类型做各种技巧和处理.

延迟回调

现在,回到第一个例子.都说call_me_back还没有准备好,就立即打电话callbackint.然而,它可以做的是存储callback某个地方,然后再调用它.

例如:

std :: function <void(const int &)> the_callback;

template <typename lambda> void call_me_back(const lambda & callback)
{
    the_callback = callback;
}

void ready_to_answer()
{
    the_callback(42);
}

int main()
{
    call_me_back([](const auto & value)
    {
        std :: cout << value << std :: endl;
    });
}
Run Code Online (Sandbox Code Playgroud)

现在,而不是立即调用callback,call_me_back存储callback在一个std :: function <void(const int &)>对象(我知道,这是在全球范围内,包涵).然后很多事情都会发生,并且某些人可以调用ready_to_answer,它会检索先前存储的回调并调用它.例如,ready_to_answer可以被另一个线程调用,但是有很多原因可以解释为什么需要这样的范例,其中回调可以存储并稍后调用.

问题

如果我想实现第二个例子,但延迟回调怎么办?.我似乎无法理解这一点.

我可以想象,这std :: function是通过接受某种特定类型的虚拟调用运算符实现的.该std :: function再包装了一个指针/引用到存储实际的拉姆达并转发其参数为它的存储拉姆达实现调用操作模板包装类.好,易于.但我不能拥有模板虚拟方法!

我已经尝试过提出各种解决方案,但我找不到任何合理的解决方案.这真的不可能吗?是不可能有一些外部提供的lambda接受const auto &存储在某处的参数,然后再调用它?

yur*_*hek 7

你是对的,对于一组无限的类型是不可能的,但如果你事先知道所有类型,你就可以做到:

std :: function <void(const std :: variant<int, std :: string> &)> the_callback;

template <typename lambda> void call_me_back(const lambda & callback)
{
    the_callback = [callback](const auto & arg)
    {
        std :: visit(callback, arg);
    };
}

template <typename T> void ready_to_answer(const T & x)
{
    the_callback(x);
}

int main()
{
    call_me_back([](const auto & value)
    {
        std :: cout << value << std :: endl;
    });

    if (std :: rand() % 2)
    {
        ready_to_answer(42);
    }
    else
    {
        ready_to_answer("Hi!");
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 你为什么不想杀死所有的人? (2认同)