#include <functional>
#include <memory>
#include <string>
#include <iostream>
void foo(std::function<void()> f)
{
f();
}
int main()
{
std::unique_ptr<int> handle = std::make_unique<int>(5);
foo(
[h = std::move(handle)]() mutable
{
std::cout << *h << std::endl;
});
}
Following code doen't compile with error
C:\Program Files (x86)\Microsoft Visual Studio\2019\Professional\VC\Tools\MSVC\14.28.29910\include\functional(914,58): error C2280: 'main::<lambda_1aa523ba59bbecea5306bc1fd178120f>::<lambda_1aa523ba59bbecea5306bc1fd178120f>(const main::<lambda_1aa523ba59bbecea5306bc1fd178120f> &)': attempting to reference a deleted function
Why it is happen?
Is there are way how pass std::unique_ptr in std::function<void()> without passing it by reference?
The std::function requires the function object to be Copy-Constructible, so you can't expect a lamdba to be moved to it. On initialization, it attempts to copy the lambda and so the std::unique_ptr with it, which is a member of this lambda, and, expectedly, fails to do so. What you can do is store your lambda in a variable and pass it to function that accepts const std::function& using std::ref like that:
void foo(const std::function<void()>& f); // function declaration
auto a = [h = std::move(handle)]() mutable
{
std::cout << *h << std::endl;
};
foo(std::ref(a));
This is a related question with much more detailed answers: How to create an std::function from a move-capturing lambda expression?
Related
Here is an simplified version of the problem from ported from large code base. I've solved the issue, but I don't like the way I solved it.
The problematic code that doesn't compile is this I'm starting with:
#include <iostream>
#include <cstdlib>
#include <vector>
#include <cassert>
#include <algorithm>
#include <cmath>
#include <array>
#include <utility>
#include <set>
#include <functional>
class S {
public:
int a;
int b;
mutable int c;
void set_c() { c = 222; }
};
struct cmp
{
bool operator()(const S& lhs, const S& rhs) const
{
return !(lhs.a == rhs.a && lhs.b == rhs.b);
}
};
class core {
public:
std::set<S, cmp> set_of_S;
std::function<void()> f;
void set_fn() {
f = [this]() {
auto it = set_of_S.begin();
it->set_c();
};
}
};
int main()
{
core core;
S a {.a = 2, .b = 3, .c = 0};
S b {.a = 2, .b = 3, .c = 0};
S c {.a = 2, .b = 4, .c = 0};
core.set_of_S.insert(a);
core.set_of_S.insert(b);
core.set_of_S.insert(c);
core.set_fn();
core.f();
std::cout << core.set_of_S.size() << '\n';
}
The compiler error is:
prog.cc: In lambda function:
prog.cc:37:23: error: passing 'const S' as 'this' argument discards qualifiers [-fpermissive]
it->set_c();
Ok, makes sense. As some people have told me, you should use the keyword mutable as this is not captured as a const and iterator it should be modifiable now (or atleast what I'm expecting):
void set_fn() {
f = [this]() mutable {
auto it = set_of_S.begin();
it->set_c();
};
}
This doesn't compile. This part doesn't make sense to me. So a member function cannot modify captured this inside lambda, but if you try to directly modify S::c inside the lambda compiler thinks that is okay. What? Doesn't make sense to me.
When I change:
void set_c() { c = 222; }
to
void set_c() const { c = 222; }
It will finally compile, but I don't like the solution, because we had to modify the original function signature just because the lambda won't accept it and it makes it less readable. I see lambdas as a tool and not something you have to design against. I have tried placing mutable keyword all over the place, but can't get it to compile. And I think there should be a way to permit member function to modify it's own state inside lambda.
Am I missing something or is this a compiler bug?
Here is the problematic code in wandbox: https://wandbox.org/permlink/qzFMW6WIRiKyY3Dj
I know this has been asked in: error: passing xxx as 'this' argument of xxx discards qualifiers but answers won't discuss on using mutable which to my understanding should solve these kind of situations.
Elements of a std::set<T> are unmodifiable - set_of_S.begin() returns a constant iterator: cppreference
Because both iterator and const_iterator are constant iterators (and may in fact be the same type), it is not possible to mutate the elements of the container through an iterator returned by any of these member functions [begin/cbegin].
That means that the element pointed to by the iterator it is const, so you can't call a non-const function such as set_c on it. it->c = 300 still works because you've made c mutable. It has nothing to do with the lambda you're calling this in being mutable or not.
I have a class with static and overloaded member function.
I want to use one them as a custom deleter in a unique_ptr
there are lots of questions on this topic, none of them worked for me.
#include <iostream>
#include <memory>
#include <functional>
class A {
public:
static void release() {
std::cout << "void released\n";
}
static void release(int*i) {
std::cout << *i << " released\n";
}
};
int main()
{
int i = 10;
std::unique_ptr<int, decltype(&A::release(int*))> ptr(&i, &A::release); // compiler error
std::unique_ptr<int, std::function<void(int*)>> ptr(&i, &A::release); // compiler error
return 0;
}
try it out here: https://onlinegdb.com/H14txk3sL
std::unique_ptr<int, void(*)(int*)> ptr(&i, &A::release);
// ~~~~~~~~~~~~^
This way, std::unique_ptr's constructor will expect a specific type of a pointer, which will help the compiler resolve ambiguity.
This:
decltype(&A::release(int*))
is not a valid syntax. In order yo use decltype(e), you'd have to write decltype(&A::release), but this again would raise an ambiguity error, and so it would have to become:
decltype(static_cast<void(*)(int*)>(&A::release))
but that's a long-winded way of saying void(*)(int*).
This:
std::function<void(int*)>
doesn't help in resolving ambiguity, becuase std::functions's constructor is a template as well, which means the compiler again misses a context that would help it to choose one of the overloaded functions.
I have been playing around with function pointers in c++ and seem to have found a bit of a problem. I made a demo to reproduce the error in a simple example.
I have the header file
class MyClass
{
public:
void MyFunction(int i);
MyClass();
~MyClass();
};
and the cpp file
#include "MyClass.h"
#include <iostream>
#include <functional>
using namespace std;
MyClass::MyClass()
{
//doesn't work
function<void(int)> func = &MyClass::MyFunction;
}
void MyClass::MyFunction(int i)
{
cout << i << endl;
}
In the constructor of the cpp file I am trying to create a pointer to MyFunction. It gives the error error C2664: 'void std::_Func_class<_Ret,int>::_Set(std::_Func_base<_Ret,int> *)' : cannot convert argument 1 from '_Myimpl *' to 'std::_Func_base<_Ret,int> *' in the functional file at line 506. It works fine with a parameterless method, but not with them. Does anyone know why, and how to resolve it?
You can use this and bind the object being constructed to the function. For instance, if your constructor looked like this:
MyClass::MyClass()
{
function<void(int)> func = bind(&MyClass::MyFunction, this, placeholders::_1);
func(6);
}
And you created a MyClass instance:
MyClass instance;
Then 6 will be printed to stdout.
You can also use std::mem_fn in C++11, which wraps a member function/variable into a callable closure
#include <iostream>
#include <functional>
class MyClass
{
public:
MyClass()
{
auto func = std::mem_fn(&MyClass::MyFunction);
func(this, 42); // call it on the current instance
}
void MyFunction(int i)
{
std::cout << i << std::endl;
}
};
int main()
{
MyClass foo;
}
or, you can explicitly specify the instance you're calling the pointer to member function
MyClass()
{
auto func = &MyClass::MyFunction;
(this->*func)(42); // call it on the current instance
}
In particular, note that std::function<void(int)> is not convertible to a pointer to member function. See related Using generic std::function objects with member functions in one class
That's why using auto with std::mem_fn gets rid of all the pain.
#include <functional>
#include <iostream>
class Foo{
void print(std::function<void (void)> f){
f();
std::cout << "!";
}
void sayHello(){
std::cout << "Hello";
}
public:
void tell(){
print(sayHello);
}
};
int main(){
auto foo = Foo();
foo.tell(); // 'Foo::sayHello': function call missing argument list; use '&Foo::sayHello' to create a pointer to member
}
I am getting the error C3867: 'Foo::sayHello': function call missing argument list; use '&Foo::sayHello' to create a pointer to member. If I use &Foo::sayHello then I'll get a bunch of templating errors.
What did I do wrong?
sayHello is a non-static member function, so it has an implicit first argument, the this pointer. The simplest way to get your code to work is to use a lambda expression that captures the this pointer.
void tell(){
print([this]{sayHello();});
}
Another option is std::bind
void tell(){
print(std::bind(&Foo::sayHello, this));
}
You want to pass a member function as argument, however a member function must be called on an object instance.
A possible solution is the following:
void tell(){
print(std::bind(&Foo::sayHello, this));
}
A member function has an additional parameter: the this pointer. You are just assuming the declaration of the function has none
void (void)
The bind() function can help you bind that pointer into it and return an object suitable for a std::function wrapper
#include <functional>
#include <iostream>
class Foo{
void print(std::function<void (void)> f){
f();
std::cout << "!";
}
void sayHello(){
std::cout << "Hello";
}
public:
void tell(){
print(std::bind(&Foo::sayHello, this));
}
};
int main(){
auto foo = Foo();
foo.tell();
}
I can easily bind member functions to a std::function by wrapping them with a lambda expression with capture clause.
class Class
{
Class()
{
Register([=](int n){ Function(n); });
}
void Register(std::function<void(int)> Callback)
{
}
void Function(int Number)
{
}
};
But I want to bind them directly, something like the following.
// ...
Register(&Class::Function);
// ...
I think according to the C++11 standard, this should be supported. However, in Visual Studio 11 I get these compiler errors.
error C2440: 'newline' : cannot convert from 'int' to 'Class *'
error C2647: '.*' : cannot dereference a 'void (__thiscall Class::* )(int)' on a 'int'
I think according to the C++11 standard, this should be supported
Not really, because a non-static member function has an implicit first parameter of type (cv-qualified) YourType*, so in this case it does not match void(int). Hence the need for std::bind:
Register(std::bind(&Class::Function, PointerToSomeInstanceOfClass, _1));
For example
Class c;
using namespace std::placeholders; // for _1, _2 etc.
c.Register(std::bind(&Class::Function, &c, _1));
Edit You mention that this is to be called with the same Class instance. In that case, you can use a simple non-member function:
void foo(int n)
{
theClassInstance.Function(n);
}
then
Class c;
c.Register(foo);
According to Stephan T. Lavavej - "Avoid using bind(), ..., use lambdas".
https://www.youtube.com/watch?v=zt7ThwVfap0&t=32m20s
In this case:
Class()
{
Register([this](int n){ Function(n); });
}
You can use std::bind:
using namespace std::placeholders; // For _1 in the bind call
// ...
Register(std::bind(&Class::Function, this, _1));
In C++ 17, you can use:
Register([=](auto && ...args){ return Function(args...); });
which is sweet especially if the argument list is longer long.
Of course the member function's argument list must then be compatible with the std::function's ones.
With std::function and std::bind, you can treat different class member function the same.
#include <iostream>
#include <functional>
#include <vector>
using namespace std;
using namespace std::placeholders;
class Foo
{
public:
void foo(const string &msg)
{
cout << msg << '\n';
}
};
class Bar
{
public:
void bar(const string &msg, const string &suffix)
{
cout << msg << suffix << '\n';
}
};
int main(int argc, char **argv)
{
Foo foo;
Bar bar;
vector<function<void (const string &msg)>> collection;
collection.push_back(bind(&Foo::foo, &foo, _1));
collection.push_back(bind(&Bar::bar, &bar, _1, "bar"));
for (auto f : collection) {
f("foo");
}
return 0;
}