【问题标题】:C++ how to wrap a variadic function template's parameter pack -> into a lambdaC ++如何将可变参数函数模板的参数包 -> 包装到 lambda 中
【发布时间】:2023-03-14 23:22:01
【问题描述】:

我想构建一个 functon 模板,它接受任何函数指针及其参数列表 - 并返回一个(有状态的)lambda,该 lambda 将这些参数值绑定在内部(想想 std::bind 但基于 lambda )

#include <iostream>
#include <vector>

template <class ...D>
class DEB;

template <class Ret, class ... Args>
auto getLambdaFromFunction(Ret(*func)(Args...)) {
    return [func](Args ... ar){ // auto could work here but lambda is anyway templated by external template's Args
        func(ar...);
    };
}

template <class Ret, class ... Args>
auto wrapFunction(Ret(*func)(Args...),Args... args) {
    return [=](){
        func(args...);
    };
}

int doone(int a, float b) {
    std::cout << "do one";
    return a;
}

int main() {
    auto lw = getLambdaFromFunction(doone); // compiles
    lw(1,2.); // invokation works

    auto lambda_parameters_binded = wrapFunction(doone, 1,2.); // **ERROR**: no matching function for call
lambda_parameters_binded(); // see mom, no hands ie no arguments!
}

我相信我需要以某种方式在 wrapFunction 的 lambda 中捕获可变参数 默认的 [=] 捕获似乎不理解可变参数列表

【问题讨论】:

  • 您应该能够在 lambda 的捕获中扩展参数包 - 请参阅 Lambda Captures here
  • @mattnewport 所以当我在调用 func(args...) 时引用 lambda 体内的参数包时 - 它应该自动将其所有元素扩展为 lambda 的 [=] capture ,对吗?一切都应该开箱即用?
  • @mattnewport 我只是试着写 return [func,args...](){ func(args...); }; -- 但它仍然没有绑定到 wrapFunction 模板

标签: c++ c++11 lambda variadic-templates


【解决方案1】:

你应该仔细阅读错误描述,现在函数接受float,但是你将double作为第三个参数传递。传递 float 将使其工作:

auto lambda_parameters_binded = wrapFunction(doone, 1, 2.0f);

Run in online compiler

还要注意生成的 lambda 不会返回任何内容,您应该在 lambda 主体内添加另一个 return 语句:

return
(
    [=](void)
    {
        return(func(args...));
    }
);

【讨论】:

  • hmmm...它不应该只是自动缩小浮动吗?和普通函数调用一样
  • @barney 实际上函数参数(原样)将用于模板参数推导。从第一个函数参数来看,它们可能看起来是int int float,但从其余参数来看,它们可能看起来是int int double。模板参数推导不处理这种冲突,只是失败了。它不起作用,因为编译器从第一个函数参数推断 Argsint float,然后调整第二个和第三个函数参数以匹配。
  • 我明白了。所以函数模板参数推导只是因为这个冲突而被 SFINAE 默默地失败了——这导致没有任何这样的函数的实例化——>所以没有自动缩小的选项,因为编译器找不到任何类似的函数签名。哇,这很有见地。谢谢!)
【解决方案2】:

另一种解决方案是在不同的可变参数模板包中设置函数参数和传入参数。这样生成模板函数就不会有歧义了。

template <class Ret, class ... Args, class ... Params>
auto wrapFunction(Ret(*func)(Args...),Params... params) {
    return [=](){
        func(params...);
    };
}

【讨论】:

  • 有趣的解决方案!我什至无法想到这是可能的。通过这种方式,函数通过其指针类型的签名进行参数化,并且参数是自行选择的——因此可以将它们缩小到可能的类型转换。确实很酷!模板世界在许多令人惊讶的方面都非常灵活......
猜你喜欢
  • 2015-09-20
  • 1970-01-01
  • 2019-12-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多