Jen*_*fke 8 c++ lambda templates c++11
我正在尝试实现一个函数模板(在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;
}
Run Code Online (Sandbox Code Playgroud)
它们做同样的事情,它只是pass1
在单参数仿函数上工作,同时passn
取任意数.
所以现在我们尝试使用它们,首先pass1
:
auto p1 = pass1( [](int a)->void {cout << a;} ); // ERROR
Run Code Online (Sandbox Code Playgroud)
这不起作用; 编译器似乎无法告诉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) {
Run Code Online (Sandbox Code Playgroud)
我可以通过显式指定模板参数类型来解决这个问题:
auto p2 = pass1<int>( [](int a)->void {cout << a;} ); // OK
Run Code Online (Sandbox Code Playgroud)
但是,此解决方法失败了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) {
^
Run Code Online (Sandbox Code Playgroud)
奇怪的是,如果我传递一个对象,我可以调用passn
它function
:
function<void(int)> fn = [](int a)->void {cout << a;};
auto x = passn<int>(fn); // OK
Run Code Online (Sandbox Code Playgroud)
...实际上,我甚至不必指定模板参数类型:
auto y = passn(fn); // OK
Run Code Online (Sandbox Code Playgroud)
我实际需要的功能就像是passn
,但我不希望function
每次调用它时都必须在lambda周围包装一个对象.我错过了什么,或者这是不可能的?在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);
}
Run Code Online (Sandbox Code Playgroud)
(演示)
它假设您传入的类型有operator()
.它获取该函数的地址并从该成员指针中推导出参数.
如果你传递一个有多个operator()
s 的对象,该函数将失败,因为然后取其地址将是不明确的,但lambdas不会产生该问题.