Long story short, is there a simple/defined way to treat function objects/lambdas and member functions in a streamlined way?
If I understand right, if I use std::mem_fn, I need to pass an object of the correct type to the function call, i.e.
Object o;
ftncall std::mem_fun(&Object::function);
ftncall(o);
Ideally, there would be some way to 'attach' o
to that function object, perhaps as a std::weak_ptr
, so we know if o got deleted. For example, if there were a way to do something vaguely like this:
Object o;
ftncall std::mem_fn(&Object::function, o); // Or maybe std::mem_fn<Object>
ftncall();
Now, obviously, this doesn't exist (to my knowledge). Is there a way to wrap std::mem_fn in such a way that I don't loose the generality (and niceness) of std::mem_fn, but can 'attach' o
, AND still play nicely with the other function type, like std::function? Ideally, I'd still be able to use operator()
in the way that I do with std::function.
Currently the best solution I can think of is a class that looks like this:
template<class T>
class MemFunWrapper {
public:
MemFunWrapper(T* t, std::mem_fun funct) : m_t(t), m_function(funct) {}
std::mem_fun operator*() { return m_function; }
T* get() { return m_t; }
private:
T* m_t;
std::mem_fun m_function;
}
Then you could use it thusly:
(*MemFunWrapper)(MemFunWrapper->get(), args...);
But that seems pretty unwieldy to me. Also, I'd have to create an equivalent class for std::function for that to be usable in the analogous way, and that seems silly since I can already just use std::function. Ideally, I'd also be able to use the end product without knowing if I'm calling a member function or a regular function. I know I'm asking a lot - any direction would be helpful. Many thanks!
The pointer to member operators . * and ->* are used to bind a pointer to a member of a specific class object. Because the precedence of () (function call operator) is higher than . * and ->* , you must use parentheses to call the function pointed to by ptf .
Class template std::function is a general-purpose polymorphic function wrapper. Instances of std::function can store, copy, and invoke any Callable target -- functions, lambda expressions, bind expressions, or other function objects, as well as pointers to member functions and pointers to data members.
It lets you store function pointers, lambdas, or classes with operator() . It will do conversion of compatible types (so std::function<double(double)> will take int(int) callable things) but that is secondary to its primary purpose.
Many std::function implementations will avoid allocations and use space inside the function class itself rather than allocating if the callback it wraps is "small enough" and has trivial copying.
What you're looking for is std::bind instead of std::mem_fn:
#include <iostream>
#include <functional>
struct Object
{
void member()
{
std::cout << "yay!" << std::endl;
}
};
int main()
{
Object o;
auto fn = std::bind(&Object::member, o);
fn();
}
FWIW: There's a proposal for adding an overload to std::mem_fn accepting the object for inclusion in C++14.
In C++11, I usually find this is easiest done with lambdas:
std::shared_ptr<Object> o = std::make_shared<Object>();
auto ftncall = [o](){ if (o) o->function(); }
ftncall();
or, with no shared lifetime:
Object o;
auto ftncall = [&o](){ o.function(); }
ftncall();
or with a weak ptr:
std::shared_ptr<Object> o = std::make_shared<Object>();
std::weak_ptr<Object> wo = o;
auto ftncall = [ow](){ if (auto o = wo.lock()) o->function(); }
ftncall();
If you need type erasure, just stuff it into a std::function<void()>
.
Lambdas in C++11 can do much the same job as bind
does without having to rely on library functions to do it, and I personally find them much more readable.
There are some situations where bind
can do a better job in C++11, but they are corner cases at this point (in C++1y, more corners will be cut off as well).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With