I have to make an asynchronous call inside a lambda, and once the asynchronous call is terminated I have to call the lambda itself.
I try to explain my problem with code:
typedef function<void(int id)> Callback;
AsyncWork1(Callback call, int id, string)
{
//...
call(id);
}
AsyncWork2(Callback call, int id, double, string)
{
//...
call(id);
}
void AsyncWorks(Callback final_callback, int id)
{
Callback lambda = [&lambda, final_callback, id](int next_work) -> void
{
if(next_work == 1)
{
//...
AsyncWork1(lambda, 2, "bla bla");
}
else if(next_work == 2)
{
//...
//the lambda variable no longer exists
AsyncWork2(lambda, 3, 0.0, "bla bla");
}
else if(next_work == 3)
{
//...
final_callback(id);
}
};
lambda(1);
}
int main()
{
AsyncWorks(...);
AsyncWorks(...);
AsyncWorks(...);
AsyncWorks(...);
return 0;
}
The problem is that when the code exits from "AsyncWorks(...)" function, the local variable "lambda" no longer exists.
I've read several threads that talk about lambda recursive, but I haven't found any solution.
How can I solve this problem?
The basic problem is that C++ doesn't expose the this pointer of a lambda to itself.
As it happens, there are many languages where during something's definition, you cannot refer to itself. This is fixed in functional languages using a technique called the "Y Combinator".
A simple y combinator in C++ looks like:
template<class F>
struct y_combinator_t {
F f;
template<class...Args>
auto operator()(Args&&...args)
-> std::result_of_t< F&( y_combinator_t<F>&, Args&&... ) >
{
return f( *this, std::forward<Args>(args)... );
}
};
template<class F>
y_combinator_t<std::decay_t<F>> y_combinate( F&& f ) {
return {std::forward<F>(f)};
}
I'm of two minds if we should f( *this or f( f, I sometimes do either.
Use:
void AsyncWorks(Callback final_callback, int id)
{
Callback lambda = y_combinate(
[final_callback, id]
(auto& self, int next_work)
-> void
{
if(next_work == 1) {
//...
AsyncWork1(self, 2, "bla bla");
} else if(next_work == 2) {
//...
//the lambda variable no longer exists
AsyncWork2(self, 3, 0.0, "bla bla");
} else if(next_work == 3) {
//...
final_callback(id);
}
}
);
lambda(1);
}
basically, I added an implicit self parameter to the lambda function body. Caller of the operator() don't see this parameter.
Y combinator based off this post by myself with modifications.
Lambda can capture itself implicitly. To demo how? see below code it calculate factorial value.
#include <iostream>
int (* factorial)( const int) = []( const int number)
{
if( number > 1)
{
return number* factorial( number - 1);
}
else
{
return 1;
}
};
int main(int , char *[])
{
int fact = factorial( 7);
std::cout<< "7! = "<< fact<< std::endl;
}
Output 7! = 5040
If any variable is used inside lambda then lambda captures it implicitly, if it is not captured explicitly. Due to this inside lambda, name factorial referring itself, is available.
But if in place ofint (* factorial)( const int) = []( const int number){//implementation }; if auto is used like as follows,auto factorial = []( const int number){ //implementation };then g++ compiler gives following error,error: use of ‘factorial’ before deduction of ‘auto’
return number* factorial( number - 1);It is because type of factorial is not deduced, auto does not deduce for same control block. Name factorial will be available only below the declaration in case of auto.
#Yakk
To understand your answer I had to spend some time studying many c++ features, value category, rvalue, lvalue, move constructor, move assignment operator, variadic templates, variadic templates with implicit conversions, result_of_t<>, decay_t<>, forward<>.
But I don't have a thing yet, why did you put the '&' symbol here?
... std::result_of_t <F&(y_combinator_t<...
I also rewrote your solution to make it more specific for my case and easier to read and understand for me too (and for all those who are beginners with C++),
class y_combinator_t
{
public:
function<void(y_combinator_t*, int, double, string)> callback;
void operator()(int a, double b, string s)
{
this->callback(this, a, b, s);
}
};
y_combinator_t combinator = {
[id_work = 1]
(y_combinator_t* _this, int a, double b, string s) mutable -> void
{
if(id_work == 1)
{
//...
AsyncWork1(*_this, 2, 3.0, "bla bla");
id_work = 2;
}
else if(id_work == 2)
{
//...
AsyncWork2(*_this, 3, 0.0, "bla bla");
id_work = 3;
}
else if(id_work == 3)
{
//...
}
}
};
//Start works
combinator(0, 0, "");
Related
I would like to make a function that can take a function as a parameter, so that I can call the function with a specified lambda in the client code. Currently my code is this:
void Execute(float threshold,
void (*behaviour)(std::shared_ptr<cv::Mat>& image_i,
pcl::PointCloud<pcl::PointXYZ>::Ptr& cloud_i,
const int* position, int index))
However this will not compile.
using :
template <typename func>
void Execute(float threshold, func behaviour)
Will compile and work fine but I would like to constrain the client code to adhere to the function signature at compile time. I am using C++17.
Example client code:
caster.Execute(thresh,
[&](std::shared_ptr<cv::Mat>& image,
pcl::PointCloud<pcl::PointXYZ>::Ptr& cloud,
const int* position, int index) -> void {
pcl::PointXYZ origin(0, 0, 0);
float d = beam::distance(cloud->points[index], origin);
if (d > max_depth_) { max_depth_ = d; }
if (d < min_depth_) { min_depth_ = d; }
image->at<float>(position[0], position[1]) = d;
num_extracted++;
});
As you can see I would like to access variables num_extracted, min_depth_ and max_depth_ which are declared outside the scope of the lambda.
You are asking to meet two requirements:
Constrain any lambda to a given signature.
Access specific variables from within a given lambda.
Here's a working version of what I could infer from your code:
namespace cv {
struct Mat {
float m_mat [3][3] {};
template<typename TYPE_T>
float& at( int ROW, int COL ) { return m_mat[ROW][COL]; }
};
}
namespace pcl {
struct PointXYZ { int X{}, Y{}, Z{}; };
template<typename TYPE_T>
struct PointCloud {
using Ptr = std::shared_ptr<PointCloud<TYPE_T>>;
TYPE_T *points{};
int length{};
};
}
struct beam {
static float distance( const pcl::PointXYZ &PT, const pcl::PointXYZ &ORIGIN ) { return 0.0f; }
};
std::shared_ptr<cv::Mat> g_image { new cv::Mat{} };
pcl::PointCloud<pcl::PointXYZ>::Ptr g_cloud { new pcl::PointCloud<pcl::PointXYZ>{} };
int g_position [] { 0, 0 };
template<typename func>
requires std::is_invocable_v<func,
std::shared_ptr<cv::Mat>&,
pcl::PointCloud<pcl::PointXYZ>::Ptr&,
const int*,
int
>
void Execute( float threshold, func behaviour )
{
behaviour(g_image, g_cloud, g_position, 1);
}
int main()
{
int num_extracted {};
float min_depth_ {},
max_depth_ {};
Execute(1.0f, [&] ( auto &&IMAGE, auto &&CLOUD, auto &&POSITION, auto &&INDEX )
{
pcl::PointXYZ origin { 0, 0, 0 };
float d = beam::distance(CLOUD->points[INDEX], origin);
if( d > max_depth_ ) { max_depth_ = d; }
if( d < min_depth_ ) { min_depth_ = d; }
IMAGE->at<float>(POSITION[0], POSITION[1]) = d;
num_extracted++;
});
return 0;
}
There are a couple ways to constrain the lambda signature, but they all involve using std::is_invovable (or making behaviour a std::function, as others have suggested). I've opted to use the newer requires syntax.
See: C++ Constraints and Concepts
There are two sets of variables you need, but you haven't described where they will come from: i) Those to be passed to Execute, and ii) Those to be used in a specific lambda that will be passed to Execute.
2.i) These are the g_* variables. They must be visible from the scope Execute is being called in so they can be passed to the invocable behavior. In this case Execute is a global function so the variables must also be global.
2.ii) These are the variables in main. They must be visible from the scope the lambda is being created in. In this case they must be in main or global.
[EDIT]
For C++ 17 you can change Execute from:
template<typename func> requires std::is_invocable_v<...>
to
template<typename func, typename = std::include_if_t<std::is_invocable_v<...>>>
I have several void-functions that do some important things in my code.
void function1(Myclass class1, int myvar)
{
// do some stuff
}
void function2(Myclass class1, int myvar)
{
// do some other stuff
}
// ... maybe some more similar functions
I want to create a function that would return a pointer to any of these functions depending on arguments I pass. I don't know how to do it. I want to have something like
void* choosefunction(int i, int j)
{
if (i == j) return (void*)function1;
else return (void *)function2;
}
Then I would just call them by this pointer.
void *(*ptrProcFunc)(int,int);
ptrProcFunc = &choosefunction;
(*ptrr)() = ptrProcFunc(i,j);
ptrr(class1,myvar);
How to do it correctly? Thank you.
typedef is your friend.
typedef void (*func_ptr)(Myclass, int);
func_ptr choosefunction(int i, int j)
{
if (i == j) return &function1;
else return &function2;
}
Then:
func_ptr ptrr = choosefunction(i,j);
ptrr(class1,myvar);
Here is a complete example.
#include <functional>
#include <iostream>
// Typedef for convenience, called "fcn".
typedef void(*fcn)(int, int);
// You could also use c++11's std::function, which is easier
// to read than function pointers.
typedef std::function<void(int, int)> modern_fcn;
void func1(int a, int b) {
std::cout << "func1" << std::endl;
}
void func2(int a, int b) {
std::cout << "func2" << std::endl;
}
// This returns our typedef'd function pointer.
fcn pick(int i, int j) {
if (i == j) {
return &func1;
} else {
return &func2;
}
}
int main()
{
// Should call func1.
pick(1,1)(3, 5);
// Should call func2.
pick(1,2)(3, 5);
}
You have several options:
You can use an using declaration to introduce an alias for your type:
using func_ptr = void (*)(Myclass, int);
using choose_ptr = void *(*)(int,int);
// ...
func_ptr choosefunction(int i, int j) {
if (i == j) return &function1;
else return &function2;
}
// ...
choose_ptr ptrProcFunc = &choosefunction;
func_ptr ptrr = ptrProcFunc(i,j);
ptrr(class1,myvar);
You can use the auto specifier and that's all (C++14):
auto choosefunction(int i, int j) {
if (i == j) return &function1;
else return &function2;
}
// ...
auto ptrProcFunc = &choosefunction;
auto ptrr = ptrProcFunc(i,j);
ptrr(class1,myvar);
You can use the auto specifier and the trailing type (C++11):
auto choosefunction(int i, int j) -> decltype(&function1) {
if (i == j) return &function1;
else return &function2;
}
// ...
auto ptrProcFunc = &choosefunction;
auto ptrr = ptrProcFunc(i,j);
ptrr(class1,myvar);
In this case, we exploit the fact that function1 and function2 have the same type.
Your confusion (and I've seen this in a lot of people learning C or C++)) is that those are not "void functions". At best you can say they are functions not returning anything (and if you are a bit more relaxed and abuse the language we can say they are functions returning void). They are functions receiving a Myclass and an int arguments and returning nothing.
The other answers show you how you can accomplish that. I strongly encourage you to use using instead of typedef, especially for a function type:
using func_ptr = void (*)(Myclass, int);
The source of the confusion (I think) is that you first learn variable declarations:
int a
and you learn that the type of the declared entity is named on it's left.
Then you learn functions and you write:
int sum(int a, int b)
And by (wrong) analogy you say: the entity being declared is sum so it's type must be what is written on it's left, i.e. int. So you say "sum is of type int" which is wrong and induces confusions like the one in you OP.
The type of sum is "function receiving two integers as parameters and returning an integer".
To help you shed your habit, write or at least think of functions in the new trailing return type declaration syntax:
auto sum(int a, int b) -> int
The (ugly) syntax is
void (*choosefunction(int i, int j))(Myclass, int)
{
if (i == j) return &function1;
else return &function2;
}
With using (or typedef), it becomes readable:
using F = void(Myclass, int);
using FPtr = void(*)(Myclass, int); // or using FPtr = F*;
And then
F* choosefunction(int i, int j);
or
FPtr choosefunction(int i, int j);
if you inline definition, you may in c++14 use simpler auto:
auto choosefunction(int i, int j) {
if (i == j) return &function1;
else return &function2;
}
Anyway, usage would be something like:
FPtr f = choosefunction(i, j);
f(myclass, myvar);
Imagine function func that needs var during run time. Is it possible under c++ to call func without var as a parameter? That is, to have something like this
func(var, i) = func(i);
I would like to do so for the sake of simple readability. Inside my class I could set var as a global parameter and then call only func(i) but this would give troubles if I was going to use threads...
But note that func uses var during run time. Ex:
int func(int var , int i){
return i+var;
}
In fact I will have multiple calls of func(), but all thes calls share the same var. Ex: instead of
int var=2;
int res= func(var, 0) + func(var, 1) +..... func(var, n);
I would write more concisely (in it is the same var)
int var=2;
int res= func(0) + func(1) +..... func(n);
You can do this using lambdas:
auto bound_func = [var](auto i) { return func(var, i); }
Or you can have more freedom by just storing the var in a struct:
struct func_binder
{
var v_;
func_binder(var v)
: v_(v)
{ }
decltype(func(v_, i)) operator()(int i)
{
return func(v_, i);
}
};
This can be used like:
func_binder f(some_var);
f(some_i);
If var is isn't mutated by the function, then you don't need to worry about it with threads. If it is, then it should be wrapped in a structure that that synchronizes access to it somehow.
How about?:
auto func_binded = std::bind( func, var, std::placeholders::_1 );
Add a new function with the same name that takes the parameter i. This function can call the other function with
The correct var. This is called function overloading.
func(i){
func(global_var, i);
}
When declaring your function, you can specifiy a default argument. In your case it has to be the last parameter of your function.
void func(int i, int var=0);
then call it like that func(i);
which is func(i, 0);
yes you can use a default value for you var variable
declare the prototype like this:
fun(type_of_i i,typeofvar var=default_value);
try to use the most relevant value for the default value
Of course you must be able to permute the order of parameters, otherwise use the function overloading mechanism as said in a previous answer
regards
So, you have at least two solutions, the first one is simple to add to a class :
Use variadic template to build a wrapper function (my preferred solution in your case, easy to add to a class). This solution allows you to write int r = newfunc(var, 1, 2, 3); instead of repeating again and again function name :
int funcvar(int var)
{
return 0;
}
template<typename TFirst, typename ... T>
int funcvar(int var, TFirst first, T ... args)
{
return func(var, first) + funcvar(var, args...);
}
Use lambda (a little be difficult to add to a class, because you need a variable of type like std::function<int(int)> fvl and initialized in constructor or pass it by argument):
auto fvl = [var](int i) { return func(var, i); };
examples :
int main()
{
int var = 1;
// Use of variadic template
int result1 = funcvar(var, 1, 2, 3, 4, 5);
int result2 = funcvar(var, 5, 6);
// Use of lambda
auto fvl = [var](int i) { return func(var, i); };
int result3 = fvl(1) + fvl(2) + fvl(3) + fvl(4) + fvl(5);
int result4 = fvl(5) + fvl(6);
std::cout << result1 << std::endl;
std::cout << result2 << std::endl;
std::cout << result3 << std::endl;
std::cout << result4 << std::endl;
}
see here
I have a Dijkstra class which uses a priority_queue with a custom compare function. I named the queue DijkstraPriorityQueue with a using statement. Inside the class constructor, I initialize the queue. To do that, I give the compare function in a lambda expression.
For the first queue, PQ1, the compare function is { return distTo[u] > distTo[v]; } and this compiles fine, because the vector<float> distTo is a member of the class.
But for the second queue, PQ2, the function is { return distTo2[u] > distTo2[v]; } where vector<float> distTo2 is just a temporary variable inside the constructor, and that doesn't compile. (I think that's the reason at least)
Also, I randomly tried to change vector<float> distTo2 to static vector<float> distTo2 by intuition and it compiles, however I don't think this is what I want to be doing. I am not familiar with static variables inside functions, since that doesn't exist in Java or C#. At any case, what is a clean solution to make the code below compile and work as intended ?
Dijkstra.h
class Dijkstra
{
public:
Dijkstra();
~Dijkstra();
private:
vector<float> distTo;
};
Dijkstra.cpp
using DijkstraPriorityQueue = priority_queue<int, vector<int>, function<bool(int, int)>>;
Dijkstra::Dijkstra()
{
distTo = vector<float>(V, FLT_MAX);
// Compiles fine
DijkstraPriorityQueue PQ1 = DijkstraPriorityQueue([this](int u, int v)
{ return distTo[u] > distTo[v]; });
vector<float> distTo2 = vector<float>(V, FLT_MAX);
// Doesn't compile
DijkstraPriorityQueue PQ2 = DijkstraPriorityQueue([this](int u, int v)
{ return distTo2[u] > distTo2[v]; });
}
Edit:
The following code compiles too. Any clues why ? Can someone explain what capture is on lambda expressions ? Or how should I write my code properly in this specific case ?
DijkstraPriorityQueue PQ2 = DijkstraPriorityQueue([distTo2](int u, int v)
{ return distTo2[u] > distTo2[v]; });
There are two main aspects of your question:
What is this “capture” thing, and why the error?
How to specify a custom compare function for a priority queue?
These aspects are most cleanly discussed separately.
Unfortunately the presented (incomplete) example code is not well suited for discussing either aspect, so I just disregard it.
What is a lambda capture.
Consider the following code:
#include <stdio.h>
struct S
{
int a_;
void foo() const
{
// Compiles nicely:
[this]() -> void { printf( "%d\n", a_ ); }();
// Doesn't compile, oh why!:
int b = 666;
[this]() -> void { printf( "%d\n", b ); }();
}
};
auto main()
-> int
{ S{ 42 }.foo(); }
MinGW g++ 5.1.0 provides the following diagnostics (compilation errors):
x1.cpp: In lambda function:
x1.cpp:14:44: error: 'b' is not captured
[this]() -> void { printf( "%d\n", b ); }();
^
x1.cpp:14:14: note: the lambda has no capture-default
[this]() -> void { printf( "%d\n", b ); }();
^
x1.cpp:13:13: note: 'int b' declared here
int b = 666;
^
To understand the “not captured”, let's implement the lambdas manually, just doing a code transformation equivalent to what the compiler does with it:
void foo() const
{
// Compiles nicely:
//[this]() -> void { printf( "%d\n", a_ ); }();
class Functor_a
{
private:
S const* captured_this_;
public:
void operator()()
{ printf( "%d\n", captured_this_->a_ ); }
Functor_a( S const* this_capture )
: captured_this_( this_capture )
{}
};
Functor_a f_a{ this };
f_a();
// Doesn't compile, oh why!:
int b = 666;
// [this]() -> void { printf( "%d\n", b ); }();
class Functor_b
{
private:
S const* captured_this_;
public:
void operator()()
{ printf( "%d\n", b ); }
Functor_b( S const* this_capture )
: captured_this_( this_capture )
{}
};
Functor_b f_b{ this };
f_b();
}
};
The diagnostic is now more clear. Since Functor_b is a class, and since a class in C++ is completely free-standing entity, its code has no relation to or access to things in a particular invocation of foo(). So the compiler doesn't accept the reference to some unspecified b, but notes that if you really meant the b in the containing scope, then hey, that name b refers to a different variable in each call of foo, and isn't a valid choice:
x2.cpp: In member function 'void S::foo() const::Functor_b::operator()()':
x2.cpp:37:35: error: use of local variable with automatic storage from containing function
{ printf( "%d\n", b ); }
^
x2.cpp:28:17: note: 'int b' declared here
int b = 666;
^
One solution is to capture the value, i.e. copy it into the functor class instance, e.g. as follows:
class Functor_b
{
private:
int const captured_b_;
public:
void operator()()
{ printf( "%d\n", captured_b_ ); }
Functor_b( int const b_capture )
: captured_b_( b_capture )
{}
};
Functor_b f_b{ b }; // ← The capture.
f_b(); // ← Using the captured value.
Alternatively you could capture a pointer to the variable, capture by reference. In that the case the pointer is only valid for the lifetime of the variable. So you'd better not keep a functor instance around after that.
Expressed in lambda notation the capture of the value can look like this:
[b]() -> void { printf( "%d\n", b ); }();
Or like this, with a general capture-whatever's-needed-by-value =:
[=]() -> void { printf( "%d\n", b ); }();
Capturing by reference, i.e. a pointer, looks like this:
[&]() -> void { printf( "%d\n", b ); }();
How to specify a compare function for a std::priority_queue.
E.g. like this:
#include <iostream>
#include <string>
#include <queue>
#include <vector>
using namespace std;
struct S
{
string name;
int birth_year;
};
auto main() -> int
{
struct Age_sort
{
auto operator()( S const& a, S const& b )
-> bool
{ return (a.birth_year < b.birth_year); }
};
using Q = priority_queue< S, vector<S>, Age_sort >;
Q pq;
pq.push( S{ "beta", 1980 } );
pq.push( S{ "alfa", 1992 } );
pq.push( S{ "charlie", 1971 } );
while( not pq.empty() )
{
cout << pq.top().name << ' ' << pq.top().birth_year << endl;
pq.pop();
}
}
I would like to do something like this:
int main()
{
auto f = [/*some variables*/](/*take lambda function*/)
{/*something with lambda function*/};
f([/*other variables*/](/*variables to be decided by f()*/)
{/*something with variables*/});
}
I know that it is possible to pass a lambda to a function, as well as to a lambda.
The following works:
int main()
{
int x=0;
int y=0;
auto f = [x,y](double (func)(int)) -> double
{func(0); return 0.0;};
f([](int i) -> double
{return 0.0;});
}
But the following does not work (as soon as i change the scope variables to add [x])
int main()
{
int x=0;
int y=0;
auto f = [x,y](double (func)(int)) -> double
{func(0); return 0.0;}
f([x](int i) -> double //[x] does not work
{return 0.0;});
}
which gives the error:
error: function "lambda [](double (*)(int))->double::operator()" cannot be called with the given argument list
argument types are: (lambda [](int)->double)
object type is: lambda [](double (*)(int))->double
would anyone have an idea as to how to fix this, or a way around it?
I am using the intel compiler
icpc (ICC) 13.1.2 with std=c++11
Thanks
There are a couple of things to clarify regarding your question. The first of which is what is a lambda?
A lambda expression is a simple expression from which the compiler will generate a unique type that cannot be named, and at the same time it will generate an instance of the type. When you write: [](int i) { std::cout << i; } the compiler will generate a type for you that is roughly:
struct __lambda_unique_name {
void operator()(int i) const { std::cout << i; }
};
As you can see, it is not a function, but a type that implements operator() as a const member function. If the lambda did any capture, the compiler would generate code to capture the value/references.
As a corner case, for lambdas like the above, where there is no state being captured, the language allows for a conversion from the lambda type to a pointer to function with the signature of the operator() (minus the this part), so the lambda above can be implicitly converted to a pointer to function taking int and returning nothing:
void (*f)(int) = [](int i) { std::cout << i; }
Now that the basics have been stated, in your code you have this lambda:
auto f = [x,y](double (func)(int)) -> double {func(0); return 0.0;};
The rules for parameters to functions (that also apply to lambdas) determine that an argument cannot be of type function, so the argument to the lambda decays to a pointer to function (in the same way that an argument of type array decays to a pointer type):
auto f = [x,y](double (*func)(int)) -> double {func(0); return 0.0;};
At a later point you are trying to pass a lambda that has a capture as an argument. Because there is a capture, the special rule does not apply and the lambda is not convertible to a pointer to function yielding the compiler error that you see.
In the current standard you can go one of two ways. You can use type-erasure to remove the exact type of the callable entity from the signature:
auto f = [x,y](std::function<double(int)> func) -> double {func(0); return 0.0;};
Because a std::function<double(int)> can be initialized with any callable entity with the appropriate signature, this will accept the lambdas in the code below, at the cost of type-erasure that usually implies a dynamic allocation and dynamic dispatch.
Alternatively, you can drop the syntactic sugar and roll the first lambda equivalent manually, but make it generic. In this case, where the lambda is simple this could be a valid option:
struct mylambda {
template <typename F>
double operator()(F fn) const {
fn(0); return 0.0;
}
} f;
// then use the non-lambda as you tried:
f([x](int i) -> double {return 0.0;});
Finally, if you are patient enough, you can wait for C++14, where (most probably, it has not yet been ratified) there will be support for polymorphic lambdas which simplify the creation of the above class:
auto f = [](auto fn) { fn(0.0); return 0.0; } // unrolls to 'mylambda' above
Try using std::function:
#include <functional>
int main()
{
int x=0;
int y=0;
auto f = [x,y](std::function<double(int)> func) -> double
{func(0); return 0.0;};
f([x](int i) -> double {return 0.0;});
}
You may have to simply bite the bullet and implement your own functors like we did in the dark ages:
struct F {
int x;
int y;
F(int x_, int y_) : x(x_), y(y_) {}
template <typename G>
double operator() (G&& g) const {
g(0);
return 0.0;
}
};
#include <iostream>
int main()
{
int x = 0;
int y = 0;
auto f = F(x, y);
f([x](int i){return 0.0;});
f([](int i){std::cout << i << std::endl;});
}
That should keep you going until your compiler supports C++14 generic lambdas.
You could try something like the following if you know the type of the lambda beforehand, for instance:
int main()
{
int x = 0, y = 0;
auto f = [x]( int i )->double {
return (double)x;
};
auto f2 = [x,y]( decltype(f) func )->double {
return func( 0 );
};
f2( f );
return 0;
}
Or alternative you could use the <functional> library for a more generic solution, for instance:
auto f = [x,y]( std::function<double(int)> func ) { /* Do stuff */ };
You can cify a capturing lambda, but this solution has its limitations:
#include <new>
#include <utility>
namespace
{
template <typename F, int I, typename L, typename R, typename ...A>
inline F cify(L&& l, R (*)(A...) noexcept(noexcept(
std::declval<F>()(std::declval<A>()...))))
{
static L l_(std::forward<L>(l));
static bool full;
if (full)
{
l_.~L();
new (static_cast<void*>(&l_)) L(std::forward<L>(l));
}
else
{
full = true;
}
return [](A... args) noexcept(noexcept(
std::declval<F>()(std::forward<A>(args)...))) -> R
{
return l_(std::forward<A>(args)...);
};
}
}
template <typename F, int I = 0, typename L>
inline F cify(L&& l)
{
return cify<F, I>(std::forward<L>(l), F());
}
int main()
{
int x=0;
int y=0;
auto f = [x,y](double (func)(int)) -> double
{func(0); return 0.0;};
f(cify<double(*)(int i)>([x](int i) -> double //works now
{return 0.0;}));
}
Click for a working example.