When can auto be used as the type specifier of a variable initialized with a lambda function? I'm try to use auto in the following program:
#include <iostream>
#include <functional>
class A
{
const std::function <void ()>* m_Lambda = nullptr;
public:
A(const std::function <void ()>& lambda): m_Lambda (&lambda) {}
void ExecuteLambda()
{
(*m_Lambda)();
}
};
void main()
{
int i1 = 1;
int i2 = 2;
const auto lambda = [&]()
{
std::cout << "i1 == " << i1 << std::endl;
std::cout << "i2 == " << i2 << std::endl;
};
A a(lambda);
a.ExecuteLambda();
}
I'm using Visual Studio Community 2019 and when I start executing a.ExecuteLambda(), the program stops with the following exception:
Unhandled exception at 0x76D9B5B2 in lambda.exe:
Microsoft C ++ exception: std :: bad_function_call at memory location 0x00B5F434.
If I change the line const auto lambda = [&]() to const std::function <void ()> lambda = [&](), it works perfectly. Why is it not allowed to use auto? Can something be changed to allow it to be used?
A lambda expression does not result in a std::function. Instead, it creates an unnamed unique class type and that has an overload for operator(). When you pass your lambda to A's constructor, it creates a temporary std::function object, and you store a pointer to that temporary object. When A's constructor ends, that temporary object is destroyed, leaving you with a dangling pointer.
To fix this, just get rid of using pointers. That would look like
#include <iostream>
#include <functional>
class A
{
std::function <void ()> m_Lambda;
public:
A(const std::function <void ()> lambda): m_Lambda (lambda) {}
void ExecuteLambda()
{
m_Lambda();
}
};
void main()
{
int i1 = 1;
int i2 = 2;
const auto lambda = [&]()
{
std::cout << "i1 == " << i1 << std::endl;
std::cout << "i2 == " << i2 << std::endl;
};
A a(lambda);
a.ExecuteLambda();
}
You are storing a dangling std::function pointer in your A object.
A lambda expression is not a std::function object, it is a compiler-defined type that is assignable to a std::function object.
When you declare lambda using auto, it gets a unique type. To bind this lambda to the A constructor's parameter, a temporary std::function object is created, which you are storing a pointer to. But then, that temporary gets destroyed when the constructor exits, which is why you get the exception when you try to execute the std::function.
When you change the declaration of lambda to std::function instead, the A constructor's parameter is able to bind to that object as-is, and no temporary is created.
You should be passing and storing std::function objects by value instead of by pointer, eg:
#include <iostream>
#include <functional>
class A
{
std::function<void()> m_Lambda;
public:
A(std::function<void()> lambda): m_Lambda(lambda) {}
void ExecuteLambda()
{
m_Lambda();
}
};
int main()
{
int i1 = 1;
int i2 = 2;
const auto lambda = [&]()
{
std::cout << "i1 == " << i1 << std::endl;
std::cout << "i2 == " << i2 << std::endl;
};
A a(lambda);
a.ExecuteLambda();
return 0;
}
Online Demo
Related
Is it possible to get a (member) function pointer to a specific instantiation of a generic lambda?
I know I can do so for standard non capturing lambdas, and for abbreviated templates, but I can't seem to be able to get a member function pointer for the explicitly instantiated operator() call operator member function of the invented type for the generic lambda.
#include <iostream>
void f1( auto v) { std::cout << v << std::endl; }
int main() {
void (*pf)(int) = f1<int>; // OK
void (*pf2)(int) = [](int v) { std::cout << v << std::endl; } ; // OK
[](auto v) { std::cout << v << std::endl; }.operator() < int > (42); // OK
auto generic_template = [](auto v) { std::cout << v << std::endl; } ;
using generic_type = decltype (generic_template);
// void (generic_type::*pf3)(int) = &generic_type::operator()<int>; // fails to compile
pf(5);
}
The interest here is academic.
Edit:
As a note of interest to future readers the solutions offered to this question also apply to getting function pointers for lambdas with capture, in addition to generic lambdas. For example, based on the answers :
auto generic_lambda = [](auto v) { std::cout << v << std::endl; } ;
using generic_type = decltype (generic_lambda);
void (generic_type::*pf1)(int) const = &generic_type::operator();
(&generic_lambda->*pf1)(43); // OK
int x = 5;
auto capturing_lambda = [x](int v) { std::cout << v+x << std::endl; } ;
using capturing_type = decltype (capturing_lambda);
void (capturing_type::*pf2)(int) const = &capturing_type::operator();
(&capturing_lambda->*pf2)(43); // OK
Yes, and you can omit the template arguments if they can be deduced from the type being initialized (or the result type of a cast) but since the lambda isn’t mutable the member function is const and so must be the pointer-to-member.
Is it possible to get a (member) function pointer to a specific
instantiation of a generic lambda?
Lambda's operator() is const-qualified by default, you need to add const to the member function pointer type
void (generic_type::*pf3)(int) const = &generic_type::operator();
And since pf3 is a member function pointer, please note that it need a specific lambda object and uses .* or ->* to invoke.
(generic_template.*pf3)(42);
Demo
I am having problems with creating a variable of pointer-to-member-function (PTMF) type "on the fly" (that is, by pinning some arguments of an existing member function via std::bind). My question is if it is ever possible with C++11 or post-C++11 standard.
Preambula: I have a class that stores a static const array of std::functions initialized from PTMFs, hereinafter referred to as "handlers". Originally, they were regular member functions with a name and implementation so I didn't ever use C++11 and std::function. Then, I decided that many of them are nearly similar, and decided to generate them with a "generator function". I would like to avoid using templates for the generation because the number of these nearly similar handlers is going to dramatically increase in future (around 200+) and templatizing will just lead to code bloat.
If the PTMFs in question were static, I would have no problems with generating the handlers via std::bind. A simplified example:
#include <iostream>
#include <functional>
using namespace std;
struct A {
typedef function<void(int)> HandlerFn;
static void parametrized_handler(int i, const char *param) {
cout << "parametrized handler: " << param << endl;
}
static void handler(int i) { cout << "handler 1" << endl; }
int mm;
};
static const A::HandlerFn handler2 = [](int) { cout << "handler 2" << endl; };
static const A::HandlerFn handler3 = bind(A::parametrized_handler,
placeholders::_1,
"test_param");
int main()
{
A::handler(42);
handler2(42);
handler3(42);
return 0;
}
Output:
$ ./a.out
handler 1
handler 2
parametrized handler: test_param
The problem arises when I turn to non-static member functions. std::bind is not able to generate a function object that acts like a PTMF. I know that I can pass a real object as a first argument to bind and get a working function but that is not what I want: when I am initializing a static const array, there are no objects at all, and the result of bind will act as a regular non-member function anyway.
An expected implementation for non-static member functions (with an imaginary std::bind_mem binder):
#include <iostream>
#include <functional>
using namespace std;
struct A;
struct A {
typedef function<void(int)> HandlerFn;
void parametrized_handler(int i, const char *param) {
mm;
cout << "parametrized handler: " << param << endl;
}
void handler(int i) const { mm; cout << "handler 1" << endl; }
const HandlerFn handler2 = [this](int i) { mm; cout << "handler 2" << endl; };
int mm;
};
// An imaginary PTMF binder
// static const A::HandlerFn handler3 = bind_mem(A::parametrized_handler,
// placeholders::_1,
// "test_param");
int main()
{
A a;
(a.handler)(42);
(a.handler2)(42);
//(a.handler3)(42);
return 0;
}
Output:
$ ./a.out
handler 1
handler 2
So is there a way to implement a PTMF argument binding?
For binding a pointer to non static member function, you need an object.
#include<functional>
struct A {
typedef std::function<void(int)> HandlerFn;
void mem(int);
void static static_mem(int);
};
void foo() {
A a;
A::HandlerFn h1 = A::static_mem;
//This captures a by ref
A::HandlerFn h2 = std::bind(&A::mem, std::ref(a), std::placeholders::_1);
//This captures a by copy
A::HandlerFn h3 = std::bind(&A::mem, a, std::placeholders::_1);
//Change to =a for copy
A::HandlerFn h4 = [&a](int i){
a.mem(i);
};
h1(34);
h2(42);
}
Link:https://godbolt.org/g/Mddexq
Sample:
#include "stdafx.h"
#include <functional>
#include <iostream>
#include <string>
std::function<void(int)> Foo()
{
int v = 1;
int r = 2;
auto l = [v, r](int i)
{
std::cout << v << " " << r << " " << i << std::endl;
};
return l;
}
int main()
{
auto func = Foo();
func(3);
return 0;
}
Why func(3) can pass 3 to i which is the formal argument of the lambda in Foo(). I can't think out. thanks.
TL;DR: You don't pass your argument 3 into a function Foo. You pass it to a method of an object func.
A bit more detailed explanation is below.
First of all, I would like to clarify what a lambda is. A lambda in C++ is nothing more than an anonymous functor class, so essentially just a syntactic sugar. A closure is an instance of a lambda type. However, quite often you can hear words "lambda" and "closure" being used interchangeably.
So within your function Foo() you create a closure object l
auto l = [v, r](int i)
{
std::cout << v << " " << r << " " << i << std::endl;
};
which would be technically equivalent to this code:
struct Functor
{
Functor(int v, int r) : v_(v), r_(r) {}
void operator ()(int i) const {
std::cout << v_ << " " << r_ << " " << i << std::endl;
}
private:
int v_;
int r_;
};
Functor l(v, r);
Now, on the next line you return an std::function object.
return l; // actually creates std::function<void(int)>(l) and returns it
So in your main function a func is just an object which stores copies of values v, r obtained during a call to Foo() and defines operator(), similar to the struct above.
Therefore, calling func(3) you actually invoke an object method on a concrete object func, and without syntactic sugar it looks like func.operator()(3).
Here's a live example to illustrate my point.
Hope that helps to resolve your confusion.
Recently I tried to reinvent scope guard via std::unique_ptr (NOTE: Deleter has the member typedef pointer — is a specially handled case of std::unique_ptr):
#include <type_traits>
#include <utility>
#include <memory>
#include <iostream>
#include <cstdlib>
#include <cassert>
namespace
{
template< typename lambda >
auto
make_scope_guard(lambda && _lambda)
{
struct lambda_caller
{
using pointer = std::decay_t< lambda >;
void
operator () (lambda & l) const noexcept
{
std::forward< lambda >(l)();
}
};
return std::unique_ptr< std::decay_t< lambda >, lambda_caller >(std::forward< lambda >(_lambda));
}
}
int
main()
{
std::cout << 1 << std::endl;
{
std::cout << 2 << std::endl;
[[gnu::unused]] auto && guard_ = make_scope_guard([&] { std::cout << __PRETTY_FUNCTION__ << std::endl; });
std::cout << 3 << std::endl;
}
std::cout << 5 << std::endl;
return EXIT_SUCCESS;
}
Such an approach works fine for simple pointer to free function void f() { std::cout << 4 << std::endl; } passed to make_scope_guard, but not for any lambda passed to make_scope_guard.
This is due to an abundance of ... = pointer() into the std::unique_ptr definition (function default parameter, defaulting data memebers etc), but I can't find the DefaultConstructible requirement for pointer into this article.
Is it mandatory, that the pointer should match the std::is_default_constructible requirement?
It tested against libc++ and against libstdc++ using not too old clang++ -std=gnu++1z.
Seems, there should be language extension for lambdas: if auto l = [/* possible capture list */] (Args...) { /* code */; }; then using L = decltype(l); is equivalent to struct L { constexpr void operator () (Args...) const noexcept { ; } }; for some Args..., isn't it?
ADDITIONAL:
Providing the instance D{} of following DefaultConstructible class to make_scope_guard(D{}) requires commented out code to be uncommented in the context if (p) { ..., where p is of type D:
struct D { void operator () () const noexcept { std::cout << __PRETTY_FUNCTION__ << std::endl; } /* constexpr operator bool () const { return true; } */ };
A unique_ptr is still a pointer. You cannot shoehorn a lambda into it. From [unique.ptr]:
A unique pointer is an object that owns another object and manages that other object through a pointer.
More precisely, a unique pointer is an object u that stores a pointer to a second object p and will dispose of
p when u is itself destroyed
[...]
Additionally, u can, upon request, transfer ownership to another unique pointer u2. Upon completion of
such a transfer, the following post-conditions hold: [...] u.p is equal to nullptr
A lambda is not a pointer. A lambda cannot equal nullptr.
That said, you're already making your own local struct, why not just use that to do the RAII scope guarding itself instead of deferring to unique_ptr? That seems like a hack at best, and takes more code to boot. You could instead just do:
template< typename lambda >
auto
make_scope_guard(lambda && _lambda)
{
struct lambda_caller
{
lambda _lambda;
~lambda_caller()
{
_lambda();
}
};
return lambda_caller{std::forward<lambda>(_lambda)};
}
If you need to support release, you can wrap _lambda inside of boost::optional so that lambda_caller becomes:
struct lambda_caller
{
boost::optional<lambda> _lambda;
~lambda_caller()
{
if (_lambda) {
(*_lambda)();
_lambda = boost::none;
}
}
void release() {
_lambda = boost::none;
}
};
I have this code:
#include <iostream>
#include <functional>
struct Foo
{
int get(int n) { return 5+n; }
};
int main()
{
Foo foo;
auto L = std::bind(&Foo::get, &foo, 3);
std::cout << L() << std::endl;
return 0;
}
Seems that this:
auto L = std::bind(&Foo::get, &foo, 3);
is equivalento to:
auto L = std::bind(&Foo::get, foo, 3);
Why?
std::bind() accepts its arguments by value. This means that in the first case you are passing a pointer by value, resulting in the copy of a pointer. In the second case, you are passing an object of type foo by value, resulting in a copy of an object of type Foo.
As a consequence, in the second case the evaluation of the expression L() causes the member function get() to be invoked on a copy of the original object foo, which may or may not be what you want.
This example illustrates the difference (forget the violation of the Rule of Three/Rule of Five, this is just for illustration purposes):
#include <iostream>
#include <functional>
struct Foo
{
int _x;
Foo(int x) : _x(x) { }
Foo(Foo const& f) : _x(f._x)
{
std::cout << "Foo(Foo const&)" << std::endl;
}
int get(int n) { return _x + n; }
};
int main()
{
Foo foo1(42);
std::cout << "=== FIRST CALL ===" << std::endl;
auto L1 = std::bind(&Foo::get, foo1, 3);
foo1._x = 1729;
std::cout << L1() << std::endl; // Prints 45
Foo foo2(42);
std::cout << "=== SECOND CALL ===" << std::endl;
auto L2 = std::bind(&Foo::get, &foo2, 3);
foo2._x = 1729;
std::cout << L2() << std::endl; // Prints 1732
}
Live example.
If, for any reason, you don't want to use the pointer form, you can use std::ref() to prevent a copy of the argument from being created:
auto L = std::bind(&Foo::get, std::ref(foo), 3);
They are not the same. The generic function binder std::bind copies it's arguments. In the case of std::bind(&Foo::get,&foo,3), the pointer is copied, but when you call the bound object it still applies to the original foo object. In std::bind(&Foo::get,foo,3) the object foo is copied, and the later call applies to the bound copy, not to the original object.
You can test this by using a member function that accesses internal state of the object, bind the object in both ways, change the original object and see how the results differ.