I'm trying to implement a function template (in C++11) whose parameter is a lambda with arbitrary parameters, and return a compatible std::function object. The goal is for the returned function when called to invoke the original lambda asynchronously, but for now I'm just returning the original lambda.
The problem is simply getting the compiler to accept a lambda as the parameter of the function template. Here are some simple templates:
#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;
}
They do the same thing, it's just that pass1
only works on single-parameter functors while passn
takes an arbitrary number.
So now we try using them, first pass1
:
auto p1 = pass1( [](int a)->void {cout << a;} ); // ERROR
This doesn't work; the compiler can't seem to tell what parameters the lambda takes. Clang error message is:
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) {
I can work around this by explicitly specifying the template parameter type:
auto p2 = pass1<int>( [](int a)->void {cout << a;} ); // OK
However, this workaround fails with 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) {
^
The weird thing is that I can invoke passn
if I pass it a function
object:
function<void(int)> fn = [](int a)->void {cout << a;};
auto x = passn<int>(fn); // OK
...in fact, I don't even have to specify the template parameter type:
auto y = passn(fn); // OK
The function I actually need is going to be like passn
, but I don't want the extra verbiage of having to wrap a function
object around the lambda every time I call it. Am I missing something, or is this just not possible? Would it be possible in C++14?