How can I create a std::function with a custom allocator? - c++

To save some code lets say I have a custom allocator named MyAlloc which I have successfully used with a std::vector<int> as follows:
std::vector<int,MyAlloc<int>> vec;
now I want to save a lambda in a std::function using the custom allocator, how do I do it?
My failed attempt:
int i[100];
std::function<void(int)> f(MyAlloc<void/*what to put here?*/>{},[i](int in){
//...
});
Update: allocators in std::function have been deprecated

According to the standard, you need to give a tag type as the first argument to indicate that you want to use a custom allocator:
std::function<void(int)> f(std::allocator_arg, MyAlloc<char>{}, [i](int in){
//...
});
As pointed out by #Casey and #Potatoswatter in the comments, the template argument type given to the allocator does not matter, as long as it's an object type. So char is fine here.
Update for C++17: It turns out that the allocator support for std::function has a number of fundamental issues, which lead to it being deprecated in C++17. If you nonetheless insist on using it, be sure to carefully check your implementation before doing so. GCC's standard library never implemented those functions, but even if your standard library does, it might not behave the way that you expect.

I realize this was answered properly, but even after reading this article and the replies I struggled a bit getting the syntax correct trying to overload an allocator for std::function that cross compiles on X64, PS4, and Xbox One in VS2012.
If it's not clear to the reader you will need to declare an allocator class per Casey's comment. Although this is fairly obvious if you read all the replies, what wasn't clear was the way these allocators are passed to the object which isn't like most of the STL allocators I've used before which take an allocator type (not instance) as part of the type specification.
For std::function an instantiated allocator is supplied to the constructor of your std::function object, which is what ComicSansMS is showing above.
For using this with a member function instead of the lambda code shown in this sample, it gets a bit tricky:
#include <functional>
MyAllocType g_myAlloc; // declared somewhere and globally instantiated to persist
// sample of a member function that takes an int parameter
class MyClassType
{
public:
void TestFunction( int param )
{
}
};
MyClassType MyClass; // instantiated object
// example without allocator
// note the pointer to the class type that must precede function parameters since
// we are using a method. Also std::mem_fn is require to compile in VS2012 :/
std::function<void(MyClassType*, int)> f( std::mem_fn( &MyClassType::TestFunction ) );
// usage of function needs an instantiated object (perhaps there is a way around this?)
f( &MyClass, 10 );
// example with allocator
std::function<void(MyClassType*, int)> f(std::allocator_arg, g_myAlloc, std::mem_fn( &MyClassType::TestFunction ) );
// usage of function is the same as above and needs an instantiated object
f( &MyClass, 10 );
//or a non member function, which is much cleaner looking
void NonMemberFunction( int param )
{
}
std::function<void(int)> f(std::allocator_arg, g_myAlloc, NonMemberFunction);
Hope this helps people, it took me longer than I'd like to admit to get this working, and as much as I use this site I figured I'd leave a comment here if for no one other than myself on how to use it. :)
2 final questions to those that are smarter than myself:
Q: Is there a way to include the allocator as part of the type?
Q: Is there a way to use a member function without an instance of an object?
To update this, if you decide to pass one of these std::function objects around as a parameter to some other function, I found I needed to use std::function::assign, or else the assignment results in a shallow copy. This can be a problem if you are trying to pass it along to an object with a longer lifecycle than the original.
Example:
std::function<void(MyClassType*, int)> f(std::allocator_arg, g_myAlloc, std::mem_fn( &MyClassType::TestFunction ) );
void FunctionTakeParam( std::function<void(MyClassType*, int)> &FunctionIn )
{
// this results in a reallocation using your allocator
std::function<void(MyClassType*, int)> MyLocalFunction.assign( std::allocator_arg, g_myAlloc, FunctionIn );
// the below results in a shallow copy which will likely cause bad things
//std::function<void(MyClassType*, int)> MyLocalFunction( std::allocator_arg, g_myAlloc, FunctionIn );
...
}

Related

Using make_shared with emplace_back and push_back - any difference?

some_vector.push_back(make_shared<ClassName>());
some_vector.emplace_back(make_shared<ClassName>());
I want to check that my understanding is correct that for make_shared and in general for all other functions that returns an object those two calls are identical. Here make_shared will create a new shared_ptr, and then this pointer will be moved into the container both in push_back and emplace_back. Is this correct, or will there be some difference?
vector<T>::push_back has a T&& overload, which does the same as the vector<T>::emplace_back T&& version.
The difference is that emplace_back will perfect-forward any set of arguments to the T's constructor, while push_back only takes T&& or T const&. When you actually pass a T&& or T const& the standard specification of their behaviour is the same.
I want to add a small detail to Yakk's answer.
The forwarding of arguments for the emplace_back-case can introduce horrible bugs in doubt - even for vectors of shared pointers - if not used with special care, see for instance
#include <vector>
#include <memory>
struct SimpleStruct {};
auto main() -> int
{
std::vector<std::shared_ptr<SimpleStruct>> v;
SimpleStruct a;
v.emplace_back(std::addressof(a)); // compiles, UB
v.push_back(std::addressof(a)); // fails to compile
}
Yes, that's a kind of an extreme example since code like this should always be used with special care or questioned in general, but it emphasizes, that one should only refer to emplace_back if one hasn't the to copy object already at hands and its only purpose is to be added to the vector, and refer to push_back for all common copy/move-construction cases. It would be nice if the language/standard library could force that from scratch for emplace_back, i.e. only accepting the custom non-copy/move constructors in order to have this clear separation but even if it's possible in an acceptable way, it would be in conflict with many template-context scenarios (fast-forwarding) and the error-prone usage is still possible, although a bit more explicit.
According to my example from above, code refactorization is an important point here in doubt. Simply imagine that the previous code used raw pointers, i.e. the actual underlying bug was already persistent there and hidden by emplace_back -usage. It would also had been hidden by push_back -usage there but not as soon as you update your code to the shared pointer way.
Even if it's not relevant for your particular specific use-case, I think it's worth to be mentioned here since one should be totally confident about the underlying differences between both methods.
Thanks to Human-Compiler in the comments for mentioning my used previous wrong terminology here.
To understand this problem let's first consider what would be the result of calling std::make_shared<class_type>(),
It returns temporary object which means Xvalue an eXpiring value whose resources can be reused. Now let's see both cases,
some_vector.push_back(make_shared<ClassName>());
std::vector have two overload of push_back and one of them accept rvalue reference that isconstexpr void push_back( T&& value );
It means value is moved into new element, but how? rvalue overload of push_back will move construct new value by invoking shared_ptr( shared_ptr&& r ) noexcept; and ownership of r will be taken and r become empty.
some_vector.emplace_back(make_shared<ClassName>());
In emplace_back( Args&&... args ) element is constructed through std::allocator_traits::construct by perfect forwarding args.. through std::forward<Args>(args)..., It means rvalue will perfect forward and cause same move constructor shared_ptr( shared_ptr&& r ) noexcept; to be invoked.
Conclusion is, both push_back and emplace_back have same effect.
But what is explained above doesn't happen because compiler comes into the picture and what it does, it perform optimization, It means rather than creating temporary objects and moving them into other objects, it directly creates objects in place.
Again result is same in both cases.
Below, supporting code for compiler optimization theory is included and as you can see output only prints one constructor call.
#include <iostream>
using std::cout;
using std::endl;
class Object{
public:
explicit Object(int );
Object(const Object& );
Object(Object&& );
};
Object::Object(int ){
cout<< __PRETTY_FUNCTION__<< endl;
}
Object::Object(const Object& ){
cout<< __PRETTY_FUNCTION__<< endl;
}
Object::Object(Object&& ){
cout<< __PRETTY_FUNCTION__<< endl;
}
int main(){
[[maybe_unused]] Object obj(Object(1));
}
Output:
Object::Object(int)
some_vector.push_back(make_shared<ClassName>()); rvalue reference is passed to the function, the push_back simply calls emplace_back.
void push_back(value_type&& __x)
{ emplace_back(std::move(__x)); }

C++11 std::function and std::reference wrapper used for sorting std::set

I have a C++ class, and one of its fields is a std::set of objects. I want to write my own comparison function, or let the user specify one. In C++11 there's a new way to handle generic function types: std::function. It works with function pointers, member function pointers, lambda functions, etc.
I tried to write a simple experiment program but it keeps craching all the time, even when I do what the C++11 Wikipedia article suggets. Maybe I just don't get how std::function and std::ref are supposed to be used.
Anyway, the point is that when I created a std::function from a simple lambda function and made it a class member, the sizeof of the class grew by 22. When I created a std::function from a pointer to a global function, this std::function's sizeof was 32. So the size is big. I'm going to have many objects using the same comparison function, so I prefer to have one function used by all of them.
I have two ideas, tell me what you think. One idea, use std::ref to store a reference to a function, this way I can define one function and many objects will use it to compare the std::set elements. Second idea: if it doesn't work like that, or the resulting function object is too big anyway, maybe I can use a shared_ptr.
You may wonder: why not have one static std::function member? The answer: because then ALL objects will use the same comparison function. I want to be able to have, for example, 1000 objects, with 400 using one comparison function and 600 using a different comparison function.
Example:
class MyClass
{
public:
private:
std::function<bool (int, int)> compare;
std::set<int> set;
};
Now how do I make the std::set use the std::function, and have many MyClass objects use the same function?
I'd like to be able to change the comparison function during run-time, so that the user would be able to choose the ordering of the objects in the set (which are displayed by GUI).
The standard way to represent shared ownership is using std::shared_ptr. That adds a bit more overhead, forcing you to allocate the std::function on the heap, but a shared_ptr is smaller than a std::function and it will correctly manage its lifetime so while any objects are still using the function object it will be kept alive and will automatically be destroyed when no longer needed.
As you suggest, a reference_wrapper referring to the shared function can be used as the set's comparison object, because a reference_wrapper is callable if it wraps a callable type.
class MyClass
{
typedef std::function<bool (int, int)> func_type;
public:
MyClass(std::shared_ptr<func_type> const& f)
: compare(f), set( std::ref(*f) )
{ }
private:
std::shared_ptr<func_type> compare;
std::set<int, std::reference_wrapper<func_type>> set;
};
A reference_wrapper cannot be null (like a reference) so you must construct the std::set with a valid reference_wrapper object.
Since the std::reference_wrapper in the std::set just holds a non-owning pointer to the std::function, you need to be careful to update the set's comparison object at the same time as updating the shared_ptr, or you could drop the last reference to the function, so the shared_ptr would destroy it, leaving a dangling pointer in the set. That could be done like this:
void MyClass::replace_cmp(std::shared_ptr<func_type> const& f)
{
set = std::set<int, std::reference_wrapper<func_type>>( std::ref(*f) );
compare = f;
}
You tell the set to use your comparison function in your constructor initializer list:
class MyClass
{
public:
template<typename Fc>
MyClass(Fc compare_func)
: compare(compare_func), // Initialize the comparison function
set(compare) // Tell the set to use out function for comparison
{}
};

Why do std::function instances have a default constructor?

This is probably a philosophical question, but I ran into the following problem:
If you define an std::function, and you don't initialize it correctly, your application will crash, like this:
typedef std::function<void(void)> MyFunctionType;
MyFunctionType myFunction;
myFunction();
If the function is passed as an argument, like this:
void DoSomething (MyFunctionType myFunction)
{
myFunction();
}
Then, of course, it also crashes. This means that I am forced to add checking code like this:
void DoSomething (MyFunctionType myFunction)
{
if (!myFunction) return;
myFunction();
}
Requiring these checks gives me a flash-back to the old C days, where you also had to check all pointer arguments explicitly:
void DoSomething (Car *car, Person *person)
{
if (!car) return; // In real applications, this would be an assert of course
if (!person) return; // In real applications, this would be an assert of course
...
}
Luckily, we can use references in C++, which prevents me from writing these checks (assuming that the caller didn't pass the contents of a nullptr to the function:
void DoSomething (Car &car, Person &person)
{
// I can assume that car and person are valid
}
So, why do std::function instances have a default constructor? Without default constructor you wouldn't have to add checks, just like for other, normal arguments of a function.
And in those 'rare' cases where you want to pass an 'optional' std::function, you can still pass a pointer to it (or use boost::optional).
True, but this is also true for other types. E.g. if I want my class to have an optional Person, then I make my data member a Person-pointer. Why not do the same for std::functions? What is so special about std::function that it can have an 'invalid' state?
It does not have an "invalid" state. It is no more invalid than this:
std::vector<int> aVector;
aVector[0] = 5;
What you have is an empty function, just like aVector is an empty vector. The object is in a very well-defined state: the state of not having data.
Now, let's consider your "pointer to function" suggestion:
void CallbackRegistrar(..., std::function<void()> *pFunc);
How do you have to call that? Well, here's one thing you cannot do:
void CallbackFunc();
CallbackRegistrar(..., CallbackFunc);
That's not allowed because CallbackFunc is a function, while the parameter type is a std::function<void()>*. Those two are not convertible, so the compiler will complain. So in order to do the call, you have to do this:
void CallbackFunc();
CallbackRegistrar(..., new std::function<void()>(CallbackFunc));
You have just introduced new into the picture. You have allocated a resource; who is going to be responsible for it? CallbackRegistrar? Obviously, you might want to use some kind of smart pointer, so you clutter the interface even more with:
void CallbackRegistrar(..., std::shared_ptr<std::function<void()>> pFunc);
That's a lot of API annoyance and cruft, just to pass a function around. The simplest way to avoid this is to allow std::function to be empty. Just like we allow std::vector to be empty. Just like we allow std::string to be empty. Just like we allow std::shared_ptr to be empty. And so on.
To put it simply: std::function contains a function. It is a holder for a callable type. Therefore, there is the possibility that it contains no callable type.
Actually, your application should not crash.
§ 20.8.11.1 Class bad_function_call [func.wrap.badcall]
1/ An exception of type bad_function_call is thrown by function::operator() (20.8.11.2.4) when the function wrapper object has no target.
The behavior is perfectly specified.
One of the most common use cases for std::function is to register callbacks, to be called when certain conditions are met. Allowing for uninitialized instances makes it possible to register callbacks only when needed, otherwise you would be forced to always pass at least some sort of no-op function.
The answer is probably historical: std::function is meant as a replacement for function pointers, and function pointers had the capability to be NULL. So, when you want to offer easy compatibility to function pointers, you need to offer an invalid state.
The identifiable invalid state is not really necessary since, as you mentioned, boost::optional does that job just fine. So I'd say that std::function's are just there for the sake of history.
There are cases where you cannot initialize everything at construction (for example, when a parameter depends on the effect on another construction that in turn depends on the effect on the first ...).
In this cases, you have necessarily to break the loop, admitting an identifiable invalid state to be corrected later.
So you construct the first as "null", construct the second element, and reassign the first.
You can, actually, avoid checks, if -where a function is used- you grant that inside the constructor of the object that embeds it, you will always return after a valid reassignment.
In the same way that you can add a nullstate to a functor type that doesn't have one, you can wrap a functor with a class that does not admit a nullstate. The former requires adding state, the latter does not require new state (only a restriction). Thus, while i don't know the rationale of the std::function design, it supports the most lean & mean usage, no matter what you want.
Cheers & hth.,
You just use std::function for callbacks, you can use a simple template helper function that forwards its arguments to the handler if it is not empty:
template <typename Callback, typename... Ts>
void SendNotification(const Callback & callback, Ts&&... vs)
{
if (callback)
{
callback(std::forward<Ts>(vs)...);
}
}
And use it in the following way:
std::function<void(int, double>> myHandler;
...
SendNotification(myHandler, 42, 3.15);

Socket pointer transfer of ownership with tcp::acceptor::async_accept

I've recently started using Boost.Asio in a project and would like to know whether anyone knows a clean solution to transfer ownership of a newly created socket to tcp::acceptor::async_accept, which would in turn transfer this ownership to the accept handler function.
This isn't an incoherent desire, mind you, since the handler is to be called exactly once.
I have noticed I can't std::bind() an std::unique_ptr<> as parameter, since std::bind() requires its parameters to be CopyConstructible, and rightfully so. Not only that, but Boost's AcceptHandler concept is also required to be CopyConstructible.
So my options would be:
Go the deprecated std::auto_ptr<> way of moving objects with the copy constructor, potentially causing obscure bugs on new releases of Boost.Asio.
Use std::shared_ptr<> and have no way to take the shared ownership off the pointer once it's not needed anymore, i.e. when it reaches the actual handler function (this is how the job is done on the examples at http://www.boost.org/doc/libs/1_43_0/doc/html/boost_asio/examples.html as far as I've read).
or
You have a better idea for me.
I'm pretty much at a loss here. Can anyone enlighten me?
I tried to find a way to do this using the c++0x standard library, but could not.
Eventually I settled on writing my own rvalue_reference_wrapper and rvalue_ref() convenience class. As per usual with std::bind, you need to wrap your non copyable object in something that is copyable (reference_wrapper is the best example). You could also have just passed a pointer, but that means changing your interface.
This worked on my machine:
#include <iostream>
#include <functional>
#include <memory>
template< class T >
struct rvalue_reference_wrapper
{
rvalue_reference_wrapper( T&& t )
: t_(std::move(t))
{}
operator T&&() const volatile
{
return std::move(t_);
}
private:
T&& t_;
};
template< class T >
rvalue_reference_wrapper<T> rvalue_ref( T&& t )
{
return rvalue_reference_wrapper<T>(std::move(t));
}
void go( std::unique_ptr<int> i )
{
std::cout << *i << std::endl;
}
int main()
{
std::unique_ptr<int> i(new int(1));
auto b = std::bind( go, rvalue_ref(std::move(i)) );
//auto b = std::bind( go, std::ref(std::move(i)) ); // Wont work
b();
}
I have not made the code bulletproof, but welcome some discussion about the need for an rvalue_reference_wrapper, or how to simulate one using std::reference_wrapper.
Also, for your specific case, you will likely need to write a difference version of rvalue_reference_wrapper, which holds the object by value not by rvalue reference, since your original unique_ptr is likely going to leave scope (and be destroyed) since you are using async asio calls.

No-op deallocator for boost::shared_ptr

Is there a stock no-op deallocator in Boost to use with boost::shared_ptr for static objects, etc.
I know it's ultra-trivial to write, but I don't want to sprinkle my code with extra tiny functions if there is already one available.
Yes there is one here:
#include <boost/serialization/shared_ptr.hpp> // for null_deleter
class Foo
{
int x;
};
Foo foo;
boost::shared_ptr< Foo > sharedfoo( &foo, boost::serialization::null_deleter() );
There is, of course, a danger with the fact that you need to know the function you call doesn't store the shared_ptr for later use, as it actually goes against the policy of shared_ptr in that the underlying object remains valid until that of the last instance of the shared_ptr.
Solution uses Boost.Lambda:
#include <boost/shared_ptr.hpp>
#include <boost/lambda/lambda.hpp>
int main()
{
int *p = new int(5);
{
boost::shared_ptr<int> sp(p, boost::lambda::_1);
}
delete p;
}
'boost::lambda::_1' creates an empty functor that takes one argument.
You'll probably want to put a //comment in there to let people know why you did it, though.
If Boost <= 1.54, use boost/log/utility/empty_deleter.hpp.
If Boost == 1.55, use boost/utility/empty_deleter.hpp.
If Boost >= 1.56, use boost/core/null_deleter.hpp.
Wouldn't it be cleaner just to take an extra reference so the deallocator is never called? (Although that's still not very clean.)
I can't say that there's no function in Boost which would do the job, but it doesn't sound like something they would want to include.
EDIT: Having read the comments and a little documentation, it boils down to this:
Reference leaking. At some point, execute this:
new shared_ptr( my_global_shared_ptr );
Advantages: conceptually easy. Disadvantages: you are leaking something on the heap.
Custom deallocator. Since shared_ptr requires little of the deallocator function, an anonymous identity function like that provided in the other answer would do fine.
Advantages: leverages Boost and has absolutely no overhead. Disdvantages: requires a little documentation.
Non-static global object. If there is a global shared_ptr for your object, that should be the only means of access to it. Replace the declaration of the global with a shared_ptr intialized by new my_class. I think this is best.
There's a ticket for this on the Boost bug tracker: https://svn.boost.org/trac/boost/ticket/1913 - no activity for a long time until some murmur two weeks ago.
FWIW, this what I'm using.
I use it in unit tests to adapt a local into a shared_ptr.
// The class NoOp_sptr_Deleter can be used to construct a shared_ptr<>()
// that will NOT delete the pointee.
// This can be helpful in unit-testing. Wrapping a local as a shared_ptr.
// Do take care with the lifetimes though.
struct NoOp_sptr_Deleter
{
void operator()(void const *) const {}
};
template<typename T>
boost::shared_ptr<T> FakeSharedPtrFromRef(T& aRef)
{
return boost::shared_ptr<T>(&aRef, NoOp_sptr_Deleter() );
}