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.
Related
I really want to pass a variable that is auto (function) as input in another function.
Here is a structure that receives parameters for my xroot f:
struct my_f_params {
double flag;
auto inter_auto(double x, double y);
};
Here is the function I essentially want to have (it's based on a GSL library, so the form can't be changed). I want to be able to pass a "function" as a variable, and the only way I guessed it would happen is with auto.
After passing it, I try storing it to a new auto, But I get an error (see below):
double xrootf (double x, void * p)
{
my_f_params * params = (my_f_params *)p;
double flag = (params->flag);
auto inter_auto = (params->inter_auto);
return flag*inter_auto(x);
}
Here is an auto function that returns an auto function. This works perfectly (if xrootf is commented, I can print for example new_f(2)(2), etc):
auto new_f(double x){
auto in_result = [](double x, double y){
return x*y;
};
using namespace std::placeholders;
auto result_f = std::bind(in_result,x,_1);
return result_f;
}
The test code that proves that the auto function new_f is working good:
int main(int argc, char const *argv[])
{
auto nest_f = new_f(-0.5);
printf("%f\n", nest_f(+2));
return 0;
}
Recasting the auto function to double is not working, either (for the struct part of the code).
The error I'm getting is:
auto_pass.cpp: In function 'double xrootf(double, void*)':
auto_pass.cpp:28:42: error: unable to deduce 'auto' from 'params->my_f_params::inter_auto'
28 | auto inter_auto = (params->inter_auto);
| ^
auto_pass.cpp:28:42: note: couldn't deduce template parameter 'auto'
The aim of the code is this:
Have a function that is able to return a function (DONE W/ new_f)
Have a function that is able to take a function as a variable (the one with new_f) (Not Done)
EDIT: Here's a quick Python script that's very easy to achieve what I'm saying:
def new_f(y):
#make any number of computatioanly costly Algebra with y
def g(x):
return x*y
return g
def xroot(f,flag):
return flag-f(flag)
auto is just a placeholder for a compiler-deduced type, depending on the context in which auto is used.
In your example, you can't use auto as the return value of my_f_params::inter_auto(), because the compiler has no way to know what type inter_auto() actually returns, so it can't deduce the type of the auto. You would need to do this instead:
struct my_f_params {
double flag;
auto inter_auto(double x, double y) { return ...; }
};
Then the compiler can deduce the type of the auto from the return statement.
Without that inline code, you would have to be explicit about the return type, eg:
struct my_f_params {
double flag;
double inter_auto(double x, double y);
};
double my_f_params::inter_auto(double x, double y) {
return ...;
}
But in any case, this is not what you really want. Your xrootf() function is trying to call inter_auto() with only one parameter, but my_f_params::inter_auto() is declared to take 2 parameters instead. Based on the Python script you showed, what you really want is for inter_auto to be a reference to some other external function instead. In which case, you can use std::function for that purpose (and there is no need to use std::bind() with a lambda at all).
Try this:
#include <iostream>
#include <functional>
struct my_f_params {
double flag;
std::function<double(double)> inter_auto;
};
double xrootf(double x, void * p)
{
my_f_params * params = static_cast<my_f_params*>(p);
return params->flag * params->inter_auto(x);
}
auto new_f(double x){
return [x](double y) {
return x * y;
};
}
int main(int argc, char const *argv[])
{
my_f_params p;
p.flag = 123.45;
p.inter_auto = new_f(-0.5);
std::cout << xrootf(+2, &p) << std::endl;
return 0;
}
Demo
When calling xrootf(), the resulting equation will be:
flag * (x * y)
which in this example is:
123.45 * (-0.5 * +2) = -123.45
I am trying to learn closures in C++. This example works:
auto add_n(int n) {
return [=](int x) -> int {
return x + n;
};
};
auto add_3 = add_n(3);
add_3(5); //8
What type is add_n expecting out? I would expect to be able to use a function pointer that takes in an int and returns an int as the return type?
typedef int (*fptr)(int);
fptr add_n(int n) {
return [=](int x) -> int {
return x + n;
};
};
Additionally, would anything else need to be done if I am working with templates instead? Thank you!
Each lambda has its own unnamed types, so you cannot replace auto by its real type.
Lambda with capture cannot be converted to function pointer.
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<...>>>
Say i have the following scenario:
namespace detail
{
using duk_c_function_t = std::function<duk_ret_t(duk_context*)>;
template<typename T_Return(typename ... T_Params), std::function<T_Return(T_Params)>
duk_ret_t duk_function_proxy(duk_context* ctx)
{
const int n = sizeof...(T_Params); //real number of arguments passed.
duk_idx_t num_arguments = duk_get_top(ctx); //Number of arguments from javascript
int x = duk_require_int(ctx, 0); //Get integer -> parameter no 1
const char* c = duk_require_string(ctx, 1); //Get string -> parameter no 2
}
}
template<typename T_Return(typename ... T_Params)>
duk_c_function_t duk_function(std::function<T_Return(T_Params ...) function_item)
{
return duk_c_function_t(detail::duk_function_proxy<function_item>);
}
Where duk_function returns a function of the signature duk_ret_t function(duk_context* ctx) { ... }. Now, i know how to call the function object in duk_function_proxy with the variadic templates and such. But there is one problem for me: The javascript interpreter i am using requires that, for every c-function i want to expose, i need query the parameters from the stack, as shown in duk_function_proxy. However, with that being the case, i dont know how to call the function object - i can only store the queried parameters in some sort of container, and thus i cannot call the function object with the given signature. Is there any way to store my queried parameters in some sort of container, and then unpack and pass it to the function object as parameters? I query the required parameters based on the variadic template list, as seen in the prototype.
In short:
I want to iterate over T_Params, get and store the corresponding variables using duk_require_* (in some sort of container), and then use those values to call the function object, which is passed as a template argument.
this should get you started. I've simulated the DUK interface since it's not installed on my machine but you'll get the idea:
#include <iostream>
#include <string>
#include <functional>
#include <utility>
struct duk_context;
const char* duk_require_string(duk_context*, int i)
{
static constexpr const char * strings[] = {
"i like",
"hairy",
"ducks"
};
return strings[i];
}
int duk_require_int(duk_context*, int i)
{
return i * 6;
}
template<class Type> auto get_arg(duk_context* ctx, int i) -> Type;
template<> auto get_arg<std::string>(duk_context* ctx, int i) -> std::string
{
return duk_require_string(ctx, i);
}
template<> auto get_arg<int>(duk_context* ctx, int i) -> int
{
return duk_require_int(ctx, i);
}
template<class...Args, size_t...Is>
void get_args_impl(duk_context* context, const std::function<void(Args...)>& f, std::index_sequence<Is...>)
{
using tuple_type = std::tuple<Args...>;
f(get_arg<std::tuple_element_t<Is, tuple_type>>(context, Is)...);
}
template<class...Args>
void get_args(duk_context* context, const std::function<void(Args...)>& f)
{
get_args_impl<Args...>(context, f, std::index_sequence_for<Args...>());
}
void foo(std::string a, int b, std::string c)
{
std::cout << a << " " << b << " " << c << std::endl;
}
int main()
{
duk_context* ctx = nullptr;
get_args(ctx, std::function<void(std::string, int, std::string)>(&foo));
return 0;
}
expected output:
i like 6 ducks
This question is based on Andrei's answer to my question on signature constraints.
struct S(int x, int y) {
void fun(T)(T t) if (is(T U == S!(a, b), int a, int b)) { }
}
template s(int a, int b) {
enum result = S!(a,b)();
alias result s;
}
void main() {
auto s1 = S!(1, 1)();
auto s2 = S!(2, 2)();
auto s3 = s!(3, 3);
auto s4 = s!(4, 4);
s1.fun(s1); // ok
s1.fun(s2); // ok
s1.fun(s3); // compile error
s3.fun(s1); // ok
s3.fun(s3); // compile error
s3.fun(s4); // compile error
}
I don't understand why the code is producing compile errors. Any ideas?
First, I wouldn't recommend using a naked template to generate an instance of an object/struct, because you're essentially requiring the object to be CTFE-able. If you need an instance your best option is to return it from a templated function:
#property S!(a, b) s(int a, int b)()
{
return S!(a, b)();
}
However this still doesn't seem to work with the template constraint. I think this has to be a front-end bug. From what I can tell it seems that the type returned cannot be properly checked in the is() expression unless it was already instantiated somewhere else, e.g.:
struct S(int x, int y)
{
void fun(T)(T t)
if (is(T U == S!(a, b), int a, int b))
{
}
}
#property S!(a, b) s(int a, int b)()
{
return S!(a, b)();
}
void main()
{
auto s1 = S!(1, 1)();
auto s2 = S!(2, 2)(); // comment out and you get errors in fun() call
auto s3 = s!(2, 2);
s1.fun(s3);
}
I'll file this as a bug.
Edit: Filed as Issue 8493.