I want to declare std::unique_ptr with custom deleter, which binds some arguments to the specific function:
using namespace std::placeholders;
using HandleDeleter = std::invoke_result_t<std::bind, _1, SOME_FLAG>; // !!!
using HandlePtr = std::unique_ptr<handle_t, HandleDeleter>;
void handle_destroy(handle_t *, int flags);
handle_t * raw_handle;
auto deleter = std::bind(handle_destroy, _1, SOME_FLAG);
HandlePtr ptr(raw_handle, deleter);
And this doesn't work because std::bind is a monstrous template construction on its own with unspecified return type.
How to properly declare HandleDeleter in my case?
std::bind is not a single callable, but a function-template. Thus, you would have to choose which one to pass to std::invoke_result_t, which is really messy.
Fortunately, there are better alternatives:
Use decltype:
using deleter_t = decltype(std::bind(handle_destroy, _1, SOME_FLAG));
Use template-argument-deduction for the class:
unique_ptr ptr(raw_handle, deleter);
Anyway, not using std::bind() is generally simpler, as well as more efficient due to hard-coding the function and argument used. Though you certainly are free to only hard-code part:
Use a lambda instead of std::bind(). In C++20 a stateless lambda will even become default-constructible:
auto deleter = [](handle_t* p){ handle_destroy(p, SOME_FLAG); };
Define your own custom deleter-class instead of using std::bind:
struct deleter_t {
constexpr void operator()(handle_t* p) const noexcept {
handle_destroy(p, SOME_FLAG);
}
};
And this doesn't work because std::bind is a monstrous template construction on its own with unspecified return type.
This is a hint: you're probably using the wrong tool for the job.
I would use a simple struct instead:
struct HandleDeleter
{
int _flag;
void operator()(handle_t* h) const
{
handle_destroy(h, _flag);
}
};
HandlePtr ptr(raw_handle, HandleDeleter{SOME_FLAG});
std::bind is not recommended in Modern C++. Use lambdas (or structs) instead. std::bind has several issues excellently explained in this talk by Stephan T. Lavavej “functional: What's New, And Proper Usage".
Related
The following code works, but I feel that the line worker([this](int a, long b, int* c){receiver(a, b, c);}); is sort of redundant because it is repeating the signature of receiver. Instead of passing a lambda function that in turn calls the member function, can I somehow pass the member function directly?
using callback = std::function<void(int, long, int*)>;
void worker(callback c)
{
c(1,2L,(int*)3);
}
class Caller
{
public:
Caller()
{
worker([this](int a, long b, int* c){receiver(a, b, c);});
}
void receiver(int a, long b, int* c)
{
}
};
If you have access to C++20, use bolov's answer. If not…
Though this still uses a lambda, you can take advantage of an argument pack to avoid duplicating the signature:
worker([this](auto... params) { receiver(params...); });
This requires C++14 or newer.
Perfect forwarding can be added if you have more complex types and want to avoid copies:
worker([this](auto&&... params) {
receiver(std::forward<decltype(params)>(params)...);
});
std::bind is the classical approach, that avoids the need to explicitly spell out the forwarding signature:
using namespace std::placeholders;
// ...
worker(std::bind(&Caller::receiver, this, _1, _2, _3));
C++20 also has std::bind_front; it reduces this verbiage, somewhat.
You cannot pass a pointer to a member function "directly". This is because a member function requires a specific instance of an object whose member function should get invoked. So, in some form of fashion, in some way, you cannot avoid this, or some other instance of the object, to be involved in the process. This is fundamental to C++. The only thing that can be done here is to find some syntactic sugar, which is basically all this is, here.
The cleanest way is C++20's std::bind_front:
worker(std::bind_front(&Caller::receiver, this));
Why use `std::bind_front` over lambdas in C++20?
I have the following scenario quite often in my c++17 code.
Generic example:
class Receiver{
public:
typedef std::function<void(const std::vector<uint8_t>& payload)> PROCESS_PACKET;
PROCESS_PACKET m_callback;
void run(){
while(){
// do stuff, then call callback:
m_callback(data);
}
}
};
class UsesReceiver{
public:
UsesReceiver(){
receiver.m_callback=std::bind(&UsesReceiver::processData, this, std::placeholders::_1);
receiver.run();
}
private:
void processData(const std::vector<uint8_t>& payload){
// here do something implementation specific
}
Receiver receiver;
};
What always bugs me is this part:
receiver.m_callback=std::bind(&UsesReceiver::processData, this, std::placeholders::_1);
For this example it is quite simple, since the function only takes one parameter, but as soon as you have more parameters this part is a lot of boilerplate in my opinion.
Because I am thinking:
If there is a member function whoese definition is exactly the same as the declared function pointer (e.g. arguments and function type match) there should be a simple one-liner that checks these preconditions at compile time and looks basically like this:
receiver.m_callback=std::bind_quick(&UsesReceiver::processData,this);
Where std::bind_quick, is "just like std::bind" but without placeholders if both function declarations match (checked at compile time).
Since the first couple of comments were "use lambdas instead":
This doesn't really solve the problem, because with lambdas you still have to declare "placeholders" for your function arguments:
receiver.m_callback=[this](auto && PH1) {
processData(std::forward<decltype(PH1)>(PH1));
};
As pointed out in the comments you should generally prefer lambdas over std::bind, even if it doesn't solve your issue.
It's fairly easy to create your quick_bind function using lambdas though.
template <typename Func, typename Obj>
auto quick_bind(Func f, Obj* obj) {
return [=](auto&&... args) {
return (obj->*f)(std::forward<decltype(args)>(args)...);
};
}
Then use it like so
receiver.m_callback=quick_bind(&UsesReceiver::processData, this);
It returns a lambda with a templated operator, so if your assigning it to a std::function it will work as long as there's not a mismatch in function signature.
I am of the position that you should have stopped using std::bind in c++14.
Lambdas solve 99.9% of std::bind problems cleaner and in a way more likely to be understood, and you shouldn't even write the remaining 0.1% of std::bind code (which involves passing std::binds to std::bind and the madness that results).
In the raw we get:
receiver.m_callback=[this](auto&payload){processData(payload);};
this is already simpler and clearer in my opinion. Just language primitives, no library functions involved.
If you want a helper function
In c++20, use std::bind_front or in c++17:
template<class F, class...Args>
auto bind_front( F&& f, Args&&...args ) {
return [f = std::forward<F>(f), tup=std::make_tuple(std::forward<Args>(args)...)](auto&&... more_args)
->decltype(auto)
{
return std::apply([&](auto&&...args)->decltype(auto){
return std::invoke( f, decltype(args)(args)..., decltype(more_args)(more_args)... );
}, tup);
};
}
a bit of a mess, but gives you
receiver.m_callback=notstd::bind_front(&UsesReceiver::processData, this);
Live example.
Since I also got a really good solution in one of the comments, I am going to sum it up here:
If you are lucky enough to work with c++20, you can use std::bind_front as suggested by #StoryTeller.
For the example above, that would look like this:
receiver.m_callback=std::bind_front(&UsesReceiver::processData, this);
If you do not have c++20 support, you can also use absl::bind_front.
Excerpt:
The simpler syntax of absl::bind_front() allows you to avoid known
misuses with std::bind()
Else,you can also write your own macro or function, as suggested in the answer above or in the comment by #NathanOliver.
In C++0x, we use use std::function like the following:
int normal_function() {
return 42;
}
std::function<int()> f = normal_function;
So to get an std::function instance, we have to define its type firstly. But it's boring and sometimes hard.
So, can we just use make to get a std::function instance just like std::tuple?
In fact, I just googled, C++0x doesn't provide such make facility.
Why C++0x no provide make facility?
Can we implement it?
Yes we can implement it
template<typename T>
std::function<T> make_function(T *t) {
return { t };
}
This requires that you pass a function to make_function. To prevent overload to pick this up for something other than a plain function, you can SFINAE it
template<typename T>
std::function<
typename std::enable_if<std::is_function<T>::value, T>::type
> make_function(T *t) {
return { t };
}
You cannot pass it class type function objects though and no member pointers. For arbitrary function objects there is no way to obtain a call signature (what would you do if the respective operator() is a template?). This probably is the reason that C++11 provides no such facility.
I have a one-dimensional function minimizer. Right now I'm passing it function pointers. However many functions have multiple parameters, some of which are held fixed. I have implemented this using functors like so
template <class T>
minimize(T &f) {
}
Functor f(param1, param2);
minimize<Functor>(f);
However the functor definition has lots of crud. Boost::bind looks cleaner. So that I could do:
minimize(boost:bind(f,_1,param1,param2))
However I'm not clear what my minimize declaration should like like using boost::bind. What type of object is boost::bind? Is there an easy pattern for this that avoids the boilerplate of functors but allows multiple parameter binding?
You can just use boost::function. I think boost::bind does have its own return type, but that is compatible with boost::function. Typical use is to make a typedef for the function:
typedef boost::function<bool(std::string)> MyTestFunction;
and then you can pass any compatible function with boost::bind:
bool SomeFunction(int i, std::string s) { return true; }
MyTestFunction f = boost::bind(SomeFunction, 42, _1);
f("and then call it.");
I hope that is what you want.
It also works with methods by passing the this pointer for the call as second parameter to boost::bind.
I would define minimize() this way:
minimize(boost::function< return_type(param_type1,param_type2,param_type3,...)> f)
{
...
}
Then you could call minimize() like this:
minimize(boost::bind(&class::function,actual_object,_1,_2,_3,...));
Change the parameter to a value parameter. Function objects are intentionally light weight, and boost::bind certainly is, specially crafted to fit in within space of a few bytes using boost::compressed_pair and what not.
template <class T>
void minimize(T f) {
}
Then you can pass it the result of boost::bind. Remember that boost::bind is actually a function template that returns some object of some type. So having minimize have a non-const reference parameter couldn't work.
First, you are taking your template argument as a ref-to-non-const, so the temporary returend by boost::bind won't bind to it. So you can use it like:
template <class T>
T::result_type minimize(const T &f) {
}
But if you wanted to use this with your Functors as well, they would have to have a const operator(). So perhaps by value is better:
template <class T>
T::result_type minimize(T f) {
}
I believe having the return be T::result_type will force a T to be a boost::function (rather than the complicated type bind returns), but I'm not 100%
I'm trying to use stl algorithm for_each without proliferating templates throughout my code. std::for_each wants to instantiate MyFunctor class by value, but it can't since its abstract. I've created a functor adapter class which passes a pointer around and then derefernces it when appropriate.
My Question:
Does the STL or Boost already have such an adapter class? I don't want to have to reinvent the wheel!
struct MyFunctor {
virtual ~MyFunctor() {}
virtual void operator()(int a) = 0;
}
namespace {
template<typename FunctorType, typename OperandType> struct
FunctorAdapter
{
FunctorAdapter(FunctorType* functor) : mFunctor(functor) {}
void operator()(OperandType& subject)
{
(*mFunctor)(subject);
}
FunctorType* mFunctor;
}; }
void applyToAll(MyFunctor &f) {
FunctorHelper<MyFunctor, int> tmp(&f);
std::for_each(myvector.begin(), myvector.end(), tmp); }
Cheers,
Dave
You could use the function adapters (and their shims) from functional.
#include <functional>
using namespace std;
for_each( vec.begin(), vec.end(), :mem_fun_ptr( &MyClass::f ) );
If your container contains pointers-to-objects, use mem_fun_ptr, else use mem_fun. Next to these, there are wrappers for member functions that take 1 argument: mem_fun1_ptr and mem_fun1.
#Evan: indeed, you could call the member function with the same argument for each object. The first argument of the mem_fun1 wrappers is the this pointer, the second is the member function argument:
for_each( vec.begin(), vec.end(), bind2nd( mem_fun_ptr( &MyClass::f ), 1 ) );
With more arguments, it becomes more readable to create a loop yourself, or create a custom functor that has const member variables representing the arguments.
tr1::ref may help you here --- it's meant to be a reference wrapper so that you can pass normal objects by reference to bind or function objects (even abstract ones) by reference to standard algorithms.
// requires TR1 support from your compiler / standard library implementation
#include <functional>
void applyToAll(MyFunctor &f) {
std::for_each(
myvector.begin(),
myvector.end(),
std::tr1::ref(f)
);
}
However, NOTE that compilers without decltype support MAY reject passing a reference to an abstract type... so this code may not compile until you get C++0x support.
why not use BOOST_FOREACH?
http://www.boost.org/doc/libs/1_35_0/doc/html/foreach.html
Sounds like you could benefit from Boost::Function.
If I remember correctly it's a header only library too, so it's easy to get it going with it.
What about forgetting all the wrapping of the functor pointer, and instead use
bind(functor_pointer,mem_fun1(&MyFunctor::operator());
as the functor? that way, you don't have to worry about managing the copy in any way shape or form.
Building on #xtofl's answer, since the array contains int's and not "this" pointers, I think the correct incantation is
class MyClass
{
virtual void process(int number) = 0;
};
MyClass *instance = ...;
for_each( vec.begin(), vec.end(), binder1st(instance, mem_fun_ptr(&MyClass::process) );
The only difference versus #xtofl's code is binder1st rather than binder2nd. binder2nd allows you to pass teh same number to various "this" pointers. binder1st allows you to pass various numbers to one "this" pointer.