gpt4 book ai didi

c++ - 如何制作一个函数模板,它接受一个带有可变参数的仿函数

转载 作者:可可西里 更新时间:2023-11-01 17:53:21 26 4
gpt4 key购买 nike

我正在尝试实现一个函数模板(在 C++11 中),其参数是一个具有任意参数的 lambda,并返回一个兼容的 std::function 对象。目标是在调用时返回的函数异步调用原始 lambda,但现在我只是返回原始 lambda。

问题只是让编译器接受一个 lambda 作为函数模板的参数。这里有一些简单的模板:

#include <functional>
using namespace std;

template <class Arg>
function<void(Arg)> pass1(function<void(Arg)> fn) {
return fn;
}

template <class... Args>
function<void(Args...)> passn(function<void(Args...)> fn) {
return fn;
}

它们做同样的事情,只是 pass1 只适用于单参数仿函数,而 passn 取任意数。

所以现在我们尝试使用它们,首先 pass1:

    auto p1 = pass1( [](int a)->void {cout << a;} );  // ERROR

这行不通;编译器似乎无法判断 lambda 采用哪些参数。 Clang 错误消息是:

Untitled.cpp:17:12: error: no matching function for call to 'pass1'
auto p1 = pass1( [](int a)->void {cout << a;} );
^~~~~
Untitled.cpp:6:21: note: candidate template ignored: could not match 'function<void (type-parameter-0-0)>' against '(lambda at Untitled.cpp:17:19)'
function<void(Arg)> pass1(function<void(Arg)> fn) {

我可以通过显式指定模板参数类型来解决这个问题:

    auto p2 = pass1<int>( [](int a)->void {cout << a;} );  // OK

但是,此解决方法因 passn 而失败:

    auto p3 = passn<int>( [](int a)->void {cout << a;} );

Untitled.cpp:23:12: error: no matching function for call to 'passn'
auto p3 = passn<int>( [](int a)->void {cout << a;} );
^~~~~~~~~~
Untitled.cpp:11:25: note: candidate template ignored: could not match 'function<void (int, type-parameter-0-0...)>' against '(lambda at Untitled.cpp:23:24)'
function<void(Args...)> passn(function<void(Args...)> fn) {
^

奇怪的是,如果我将 function 对象传递给它,我可以调用 passn:

    function<void(int)> fn = [](int a)->void {cout << a;};
auto x = passn<int>(fn); // OK

...事实上,我什至不必指定模板参数类型:

    auto y = passn(fn);  // OK

我实际需要的函数类似于 passn,但我不希望每次都必须在 lambda 周围包装一个 function 对象我称之为。我错过了什么,还是这不可能?在 C++14 中有可能吗?

最佳答案

你可以使用passn的这个实现:

#include <functional>
#include <iostream>

template <class RetVal, class T, class... Args>
std::function<RetVal(Args...)> get_fun_type(RetVal (T::*)(Args...) const);

template <class RetVal, class T, class... Args>
std::function<RetVal(Args...)> get_fun_type(RetVal (T::*)(Args...));

template <class T>
auto passn(T t) -> decltype(get_fun_type(&T::operator())) {
return t;
}

int main() {
auto fun = passn([](int a) { std::cout << a; });
fun(42);
}

( demo )

它假定您传入一个具有 operator() 的类型。它获取该函数的地址并从该成员指针推导出参数。

如果您向函数传递一个具有多个 operator() 的对象,该函数将失败,因为这样取其地址将是不明确的,但 lambda 不会产生该问题。

关于c++ - 如何制作一个函数模板,它接受一个带有可变参数的仿函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42124866/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com