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

标签 c++ c++11 templates lambda

我正在尝试实现一个函数模板(在 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/

相关文章:

c++ - 集合中倒数第二个的模板; reverse_iterator 不编译

c++ - 获取实例化对象的对象

c++ - 使用cmake构建静态库的静态库

c++ - 使用通用模板函数为 std::ostream 和 std::vector 专门化 operator<< 的最佳方法?

c++ - 减少基于特征的模板

c++ - 模板类/函数中的交叉转发声明

C++0x 与 using 声明的混淆

c++ - 如何找到第一个集合?

c++ - 使用 boost::serialization 跳过层次继承中的中间类

python - 在 Python 中使用正则表达式作为模板