I would like to assign a pointer to a lambda function, in which the lambda function is taking variables passed by reference, not by value.
int main() {
// what I can do, but not quite what I want
auto funcy = [](const double i ) {
std:: cout << "this is i: " << i << std::endl;
};
void(*lptr)(double); // OK
lptr = funcy;
lptr(1);
// TODO: make a variable that points to this lambda work
auto funcy2 = [](const double &i ) {
std:: cout << "this is i: " << i << std::endl;
};
void(*lptr2)(double *); // BROKE
lptr2 = funcy2;
lptr2(1);
return 0;
}
Is it possible to do this?
Thanks for your time.
Edit: This post is different from Passing capturing lambda as function pointer because I have no idea what that one is saying.
Answered by #sweenish in the comments. The "function signature" has to match. It's actually "pretty straightforward".
void(*lptr2)(const double&); // FIXED
lptr2 = funcy2;
lptr2(5);
The best would be that the type of the function pointer would match the type of the lambda function. This will be much more simple and is most likely the solution that you want.
By using pointers everywhere
auto funcy2 = [](double *i) {
std::cout << "this is i: " << *i << std::endl;
};
void(*lptr2)(double *); // matches
lptr2 = funcy2;
double i = 1;
lptr2(&i);
... or even better, references everywhere:
auto funcy2 = [](const double &i) {
std::cout << "this is i: " << i << std::endl;
};
void(*lptr2)(const double &); // works, the type match the lambda parameter
lptr2 = funcy2;
lptr2(1);
If you really want to assign a lambda to a mismatched type, you'll have to wrap it. Since there's a conversion to do, you can do it using another lambda:
static auto funcy2 = [](const double &i) {
std::cout << "this is i: " << i << std::endl;
};
auto funcy3 = [](double* i) {
funcy2(&i); // convert the pointer to a reference
};
void(*lptr2)(double *); // BROKE
lptr2 = funcy2;
lptr2(1);
Related
I need to pass structure to the function Constraint::AddFixedOrientationAxis, however when I check the passed data their values are completely wrong. I have tried to use different datatypes but without any luck.
typedef struct{
size_t idx;
size_t axis_idx;
double axis_vector_1;
double axis_vector_2;
double axis_vector_3;
}AddFixedOrientationAxisData;
double Constraint::AddFixedOrientationAxis(const std::vector<double> &x, std::vector<double> &grad, void *data)
{
Eigen::VectorXd fixed_rot(3);
AddFixedOrientationAxisData *d = reinterpret_cast<AddFixedOrientationAxisData*>(data);
auto idx = d->idx;
auto axis_idx = d->axis_idx; // 0->x, 1->y, 2->z
fixed_rot << d->axis_vector_1, d->axis_vector_2, d->axis_vector_3;
std::cout << "idx: " << idx << std::endl;
std::cout << "axis: " << axis_idx << std::endl;
std::cout << "fixed_rot: " << fixed_rot << std::endl;
}
In the main, I call use it the same way as the tutorial is:
AddFixedOrientationAxisData fixed_orient_constraint_data;
fixed_orient_constraint_data.idx = 0;
fixed_orient_constraint_data.axis_idx = 0;
fixed_orient_constraint_data.axis_vector_1 = FK_q(0,0);
fixed_orient_constraint_data.axis_vector_2 = FK_q(1,0);
fixed_orient_constraint_data.axis_vector_3 = FK_q(2,0);
opt.add_equality_constraint(Constraint::AddFixedOrientationAxis, &fixed_orient_constraint_data);
The terminal output is:
idx: 93901286131024
axis: 93901286131080
fixed_rot:
4.63934e-310
-0.54938 //interestingly, this is the correct value
0.00838157 //interestingly, this is the correct value
As #{Some programmer dude} told me in the comments, the problem was that the variable was not alive when the function was called.
Is it possible to perfectly forward *this object inside member functions? If yes, then how can we do it? If no, then why not, and what alternatives do we have to achieve the same effect.
Please see the code snippet below to understand the question better.
class Experiment {
public:
double i, j;
Experiment(double p_i = 0, double p_j = 0) : i(p_i), j(p_j) {}
double sum() { return i + j + someConstant(); }
double someConstant() && { return 10; }
double someConstant() & { return 100; }
};
int main() {
Experiment E(3, 5);
std::cout << std::move(E).sum() << "\n"; // prints: 108
std::cout << E.sum() << "\n"; // prints: 108
}
This output seems expected if we consider that *this object inside the member function double sum() is always either an lvalue or xvalue (thus a glvalue) . Please confirm if this is true or not.
How can we perfectly forward *this object to the member function call someConstant() inside the double sum() member function?
I tried using std::forward as follows:
double sum() {
return i + j + std::forward<decltype(*this)>(*this).someConstant();
}
But this did not have any effect, and double someConstant() & overload is the one always being called.
This is not possible in C++11 without overloading sum for & and && qualifiers. (In which case you can determine the value category from the qualifier of the particular overload.)
*this is, just like the result of any indirection, a lvalue, and is also what an implicit member function call is called on.
This will be fixed in C++23 via introduction of an explicit object parameter for which usual forwarding can be applied: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2021/p0847r7.html
One would think that std::forward() would preserve lvalue references but it doesn't in non-template contexts, as the example below shows.
Both call_f()& and call_f()&& call f()&&. std::forward<Experiment>(*this) in a non-template function returns an rvalue reference regardless of the value category of the argument.
Note how this works differently from a template function, member or not (I made the member function static because it receives a "this reference" as an explicit parameter) . Both forward lvalue references "properly" (the last 4 calls).
#include<iostream>
#include<utility>
#include<string>
struct Experiment
{
public:
std::string f()&& { return "f()&&"; }
std::string f()& { return "f()&"; }
std::string call_f()&& { std::cout << "call_f()&& "; return std::forward<Experiment>(*this).f(); }
// I need this function because it is not a template function
std::string call_f()& { std::cout << "call_f()& "; return std::forward<Experiment>(*this).f(); }
template<class T = Experiment>
static std::string E_t_call_f(T&& t) { std::cout << "E_t_call_f(T&& t) "; return std::forward<T>(t).f(); }
};
template<class T>
std::string t_call_f(T&& t) { std::cout << "t_call_f(T&& t) "; return std::forward<T>(t).f(); }
int main()
{
Experiment E;
std::cout << "E.f(): " << E.f() << '\n';
std::cout << "move(E).f(): " << std::move(E).f() << '\n';
std::cout << '\n';
std::cout << "E.call_f(): " << E.call_f() << '\n';
std::cout << "move(E).call_f(): " << std::move(E).call_f() << '\n';
std::cout << '\n';
std::cout << "t_call_f(E): " << t_call_f(E) << '\n';
std::cout << "t_call_f(std::move(E)): " << t_call_f(std::move(E)) << '\n';
std::cout << '\n';
std::cout << "E::E_t_call_f(E): " << Experiment::E_t_call_f(E) << '\n';
std::cout << "E::E_t_call_f(std::move(E)): " << Experiment::E_t_call_f(std::move(E)) << '\n';
}
In the resulting output it is the third line that's surprising: The type of std::forward<Experiment>(*this) for an lvalue reference to *this is an rvalue reference.
E.f(): f()&
move(E).f(): f()&&
call_f()& E.call_f(): f()&&
call_f()&& move(E).call_f(): f()&&
t_call_f(T&& t) t_call_f(E): f()&
t_call_f(T&& t) t_call_f(std::move(E)): f()&&
E_t_call_f(T&& t) E::E_t_call_f(E): f()&
E_t_call_f(T&& t) E::E_t_call_f(std::move(E)): f()&&
I am trying to use the value from a std::bitset inside of a lambda function but I am experiencing unexpected behavior:
int main()
{
auto lambda = [](unsigned int param)
{
std::bitset<10> bits(param);
std::cout << "inside lambda bits[8] = " << bits[8] << std::endl;
return bits[8];
};
// 0x11c is 1_0001_1100 in binary
auto result = lambda(0x11c);
std::cout << "result = " << result << std::endl;
}
I would expect the value of result to be one since result is of type bool which can be copied from the local stack but instead the output is the following:
inside lambda bits[8] = 1
result = 0
What am I overlooking here?
The operator[] for std::bitset returns a std::bitset::reference when called on a non-const std::bitset. This means the lambda (which deduces the return type), returns a reference to a local variable. This obviously dangles, and invokes undefined behavior when used at the call site.
You can fix this in several ways:
Explicitly specify the return type of the lambda, so the reference is converted to bool and returned by copy:
auto lambda = [](unsigned int param) -> bool
// ^^^^
{
std::bitset<10> bits(param);
std::cout << "inside lambda bits[8] = " << bits[8] << std::endl;
return bits[8];
};
Here's a demo
Make the std::bitset in the lambda const so that it calls the const overload of operator[], which returns a bool:
auto lambda = [](unsigned int param)
{
std::bitset<10> const bits(param);
// ^^^^^
std::cout << "inside lambda bits[8] = " << bits[8] << std::endl;
return bits[8];
};
Here's a demo.
Store the value of bits[8] as a bool, and return that:
auto lambda = [](unsigned int param)
{
std::bitset<10> bits(param);
std::cout << "inside lambda bits[8] = " << bits[8] << std::endl;
bool b = bits[8];
// ^^^^^^
return b;
};
Here's a demo.
I have the following:
void print_str(std::shared_ptr<std::string> str) {
std::cout << str->c_str() << std::endl;
}
int main() {
auto str = std::make_shared<std::string>("Hello");
std::function<void()> f = std::bind(print_str, str);
f(); // correctly print: Hello
return 0;
}
I think the type of std::bind(print_str, str) is std::function<void(std::shared_ptr<std::string>)>, but the code above is correctly running. Is there any trick in std::bind?
env: centos, gcc82
What std::bind does is correct. It uses the value you provided (str) for the call to print_str. So you don't need to specify it anymore and will always be replaced by the bound value.
#include <iostream>
#include <functional>
int sum(int value1, int value2) {
return value1 + value2;
}
int main() {
std::function<int(int, int)> f1 = std::bind(sum, std::placeholders::_1, std::placeholders::_1);
std::function<int(int)> f2 = std::bind(sum, 10, std::placeholders::_1);
std::function<int()> f3 = std::bind(sum, 100, 200);
std::function<int(int)> f4 = std::bind(sum, std::placeholders::_1, 200);
int a = 1;
int b = 2;
std::cout << "the sum of " << a << " and " << b << " is: " << f1(a, b) << std::endl;
std::cout << "the sum of " << 10 << " and " << b << " is: " << f2(b) << std::endl;
std::cout << "the sum of " << 100 << " and " << 200 << " is: " << f3() << std::endl;
std::cout << "the sum of " << 200 << " and " << b << " is: " << f4(b) << std::endl;
return 0;
}
output:
the sum of 1 and 2 is: 2
the sum of 10 and 2 is: 12
the sum of 100 and 200 is: 300
the sum of 200 and 2 is: 202
f1 binds no values but placeholders and returns an int(int, int) like function
f2 binds one value and one placeholder and returns an int(int) like function
f3 binds two values and no placeholder and returns an int() like function
f4 is like f2 except that the place holder is now the first parameter instead of the second one.
Your code falls into the f3 case.
I think the type of std::bind(print_str, str) is std::function<void(std::shared_ptr<std::string>)>
No, the type of std::bind(print_str, str) is an unspecified functor type, something like
class binder
{
void(*f)(std::shared_ptr<std::string>);
std::shared_ptr<std::string> p;
public:
template<typename... Args>
void operator()(Args... ) { f(p); }
};
Note that this is callable with any arguments or none.
What you are experiencing here is correct and is precisely doing what std::bind was designed for.
Simply speaking:
It turns a function taking n parameters into a function taking m parameters (where n >= m).
In your particular case, you give it a function taking one parameter and get back a function taking zero parameters. This new function will internally call print_str and always pass str as argument.
Side note:
Since there are lambdas in C++11, std::bind is sort of redundant.
What you are doing is exactly equivalent to this:
void print_str(std::shared_ptr<std::string> str) {
std::cout << str->c_str() << std::endl;
}
int main() {
auto str = std::make_shared<std::string>("Hello");
std::function<void()> f = [=]() { print_str(str); };
f(); // correctly print: Hello
return 0;
}
This hopefully also helps understanding what std::bind does behind the scenes.
How can I pack in a vector several different primitive data types as well as strings to examine the contents then?
(In Java, this went via Object [] objects = {1.0, "Hello", - 42, 'b'})
The task is as follows:
Given the following array: [3.0,42, "Monkey", 7.2, b]
This array is to be passed to a method that outputs the contents of the array on the console. If it is a string, each letter of the string should be added as an ASCII value in the same variable, and finally returned as an int on the console. With char exactly the same.
I know from today as I create a vector so with std::vector<double> numbers = {1.0,2.0}; How to write functions and how to access the indexes numbers[i]; as well as the length of the vector numbers.size().
How can I solve this problem now? Since I have unfortunately found no simple <- solution for the multiple types in a vector.
Thanks in advance :)
C++ does not do type erasure the same way that Java does. To create a heterogeneous container (which is the technical term for what you're trying to do) you'll need to make extensive use of std::any or std::variant, which are new classes introduced with C++17.
std::vector<std::any> values{1.0, "Hello", -42, 'b'};
for(auto & any : values) {
int * i;
if(val = std::any_cast<int>(&any)) std::cout << "int: " << *i << std::endl;
const char ** s;
if(s = std::any_cast<const char *>(&any)) std::cout << "string-literal: " << *s << std::endl;
double * d;
if(d = std::any_cast<double>(&any)) std::cout << "double: " << *d << std::endl;
char * c;
if(c = std::any_cast<char>(&any)) std::cout << "char: " << *c << std::endl;
}
Note how messy that code is. Not least of which because many people would desire "hello" to be stored as a std::string object, but this can't be done unless the user expressly designates it as such:
std::vector<std::any> values{1.0, std::string{"Hello"}, -42, 'b'};
At any rate, my personal opinion is that the use of std::variant would be a much better fit, as you can make it much clearer how the container is meant to be used, and you can avoid the dynamic allocations associated with std::any:
typedef std::variant<std::string, char, double, int> my_variant;
struct visitor {
void operator()(std::string const& v) const {
std::cout << "std::string: " << v<< std::endl;
}
void operator()(double const& v) const {
std::cout << "double: " << v << std::endl;
}
void operator()(int const& v) const {
std::cout << "int: " << v << std::endl;
}
void operator()(char const& v) const {
std::cout << "char: " << v << std::endl;
}
};
int main() {
std::vector<my_variant> values{1.0, "Hello", -42, 'b'};
for(my_variant & variant : values) {
std::visit(visitor{}, variant);
}
return 0;
}
We can even make the variant version a lot simpler with auto lambdas if we don't need to know the type:
typedef std::variant<std::string, char, double, int> my_variant;
int main() {
std::vector<my_variant> values{1.0, "Hello", -42, 'b'};
for(my_variant & variant : values) {
std::visit(
[](auto const& val) {std::cout << "Some unknown type: " << val << std::endl;},
variant
);
}
return 0;
}
I haven't run this through my compiler, but this should give a pretty good sense of how to accomplish this kind of task in C++.
If you don't have access to C++17, you can use boost.any and boost.variant, which I'm reasonably sure are both header-only libraries, and thus easy to import into your project.