This is specific to void() functors, but that is fine with me...
struct Foo
{
void Bar(int x)
{
std::cout << x << std::endl;
}
};
struct VoidBind
{
typedef void result_type;
template<typename T> void operator()(const std::weak_ptr<T>& obj, std::function<void()>& func)
{
std::shared_ptr<T> shared_obj = obj.lock();
if (shared_obj)
{
func();
}
}
template<typename T> static std::function<void()> bind(const std::shared_ptr<T>& obj, const std::function<void()>& func)
{
return std::bind(VoidBind(), std::weak_ptr<T>(obj), func);
}
};
#define BIND(F, O, A...) VoidBind::bind(O, std::function<void()>(std::bind(F, O.get(), ##A)))
This code is then invoked as...
auto obj = std::make_shared<Foo>();
auto func = BIND(&Foo::Bar, obj, 99); // match std::bind style
func();
obj.reset(); // destroy object
func(); // will not do anything
My question is whether there is some way to avoid the BIND macro?
Variadic templates can be used here:
template<class F, class O, class... Args>
auto bind(F f, O&& o, Args&&... args)
-> decltype(VoidBind::bind(o, std::function<void()>(std::bind(f, O.get(), args...))))
{
return VoidBind::bind(O, std::function<void()>(std::bind(F, O.get(), args...)));
}
It gets better with C++14 automatic return-type deduction where you don't even need to specify the return value:
template<class F, class O, class... Args>
auto bind(F f, O&& o, Args&&... args)
{
return VoidBind::bind(o, std::function<void()>(std::bind(f, O.get(), args...)));
}