I have a class which interpolates a 2D function automatically (quite happy with it). It accepts a dynamic function pointer to the method being interpolated. I have had to template out the class, since I need the object instance as well as the pointer.
Can I avoid templating the class out? Or will I need to keep doing so in order to accept the object instance as a parameter? Is a base class possible? (I'm fairly new to c++)
The way I have it is (abbreviated):
template<class F>
class Interpolate {
Interpolate(double (F::*f)(double, double), F & obj, ...) {
...
double value = (object.*f)(x,y);
...
}
}
As pointed out in the comment, you can also use std::function. This give you more flexibility with std::bind. On the other hand, std::function may allocate the resulting function on the heap and this causes a big overhead (which may be avoid by using std::cref() ). A very interesting discussion about the differences in execution time of std::function vs templates can be found at std::function vs template.
" Notice that std::function is able to store different types of callable objects. Hence, it must perform some type-erasure magic for the storage. Generally, this implies a dynamic memory allocation (by default through a call to new). It's well known that this is a quite costly operation. " by Cassio Neri - Here is where std::cref can help, specially because in the example discussed in the link I just wrote, without std::cref, the heap allocation of std::function slowed down the program by a factor 10!
Related
I have a lambda I'm storing into an std::function to be called in a separate thread, that looks like this:
void * specialMalloc(size_t size); // provides annointed memory; beloved by all
int n;
std::function f = [=]()mutable -> void {
printf("%i", n);
};
Is it possible to create a std::function f that takes this lambda and it's int n, and asks specialMalloc() to carefully prepare memory to place it into? Specifically in C++17, where I've read custom allocators have been deprecated?
There's no way custom to pass allocator in the current C++. std::function will use global operator new. It will not even use class's operator new, instead calling the global one.
However std::function typically employs small object optimization. At least you expect it to engage for pointer-sized functors. Real implementations have buffer for small object optimization for 2-3 pointers, MSVC has much more. With small object optimization, std::function does not use indirect memory at all.
Your functor has a size of int, which is very likely to fit small object optimization. You functor will not cause any allocation function to be called when it is put into std::function.
For larger functors, you can make their data indirect, and allocate it on your own, so that they'll make use of small object optimization, and thus will not use the global operator new
There are other criteria for small object optimization to engage, specifically noexcept copy constructor, and not being overly alignend.
Unfortunately, there's no standard way to query in compile-time whether small object optimization apply, and it is not required by the standard (although recommended for some types of functors)
I think there's not a good way to do this.
Well, std::function had a constructor that took a custom allocator but this functionality was removed in C++17.
When a std::function is copied, are the code instructions it references copied as well?
An std::function is initialized via some form of callable, that points to executable code in some way (like a function pointer typically does). Now, when a function-object is copied, is this executable code runtime copied or internally referenced?
To rephrase the question: If one instance of std::function is copied, are there then multiple copies of the same compiled code instructions in memory?
Is std::function an object that actually stores the function code or is it more an abstraction for a function pointer?
The former would seem wasteful and I don't suspect it, but everything I found so far on the subject is either too vague, lacking or too specific for me to say for me for sure. For example
When the target is a function pointer or a std::reference_wrapper, small object optimization is guaranteed, that is, these targets are always directly stored inside the std::function object, no dynamic allocation takes place. Other large objects may be constructed in dynamic allocated storage and accessed by the std::function object through a pointer. - cppreference
gives some hints about how it's done but seems still too vague and maybe is not related at all to this question, because of further abstractions inside of std::function.
For context: I am trying to refactor some bad C-ish code that maps input-events (keystrokes, mouse input and the like) to a certain behavior, which is executed upon a target data structure which can be interpreted by the program as more specific input that have semantic context other than than keystrokes (, aka keybindings). One can suspect that requirements of behaviours varies drastically.
This was previously implemented with lists of defines and numbers specifying input-event-ids, and hard-coded behavior, which was selected by switch-case. We quickly approach the border of where this intial way of doing it becomes unwieldly.
To get out of the defined lists to an expandable, declarative, object oriented and flexible design I consider higher order functions.
Especially since some behavior is quite simple and repeatedly needed (like for example the toggle of one value in the output data structure) other behaviors are more complex with multiple conditions attached, I'd like to declare some of the behavior statically, but still would like to be open to just assign some special lambda in some cases. Since I need to store behavior per input (key, mousebutton, mouse-axis, etc.) and potentially many copies of one certain behaviour type can be instantiated in one time for different sets of keybindings, I wonder if this behavior should be referenced, rather than stored by value. In the former case, fresh lambdas would need to be owned by the behavior structures, but statically declared behavior does not, which pragmatically would lead to some shared_ptr shenanigans. In the latter case, by value, this would not be an issue, but I wouldn't want multiple copies of for example the toggle behavior to cause too much redundant overhead instead.
(Note: the whole discussion below is a little simplified. AFAIK, none of it is wrong, but I did omit some details and edge cases and definitions and implementation stuff.)
The std::function does not copy any executable code. The executable code is always merely pointed to, by std::function. And when the std::function gets copied, the pointer gets duplicated (which is completely fine, because executable code is never freed either.) So far, there is no difference between a plain old function pointer and a std::function.
But that's not the whole story.
Contrary to function pointers, instances of std::function can carry around "state" as well as a pointer to the executable code, and the whole hubbub about std::function having to allocate/deallocate and copy/move data around is about this extra state, not the function pointer.
Suppose that you have code like this:
(And note that although I've used a lambda here, the following explanation would have been equally applicable for "functors" and "function objects" and "bind results" and other forms of callable things in C++, all except plain old function pointers.)
int x = 42, y = 17;
std::function<int()> f = [x, y] {return x + y;};
Here, f not only stores the pointer to the executable code for return x + y;, but it also has to remember the value of x and y. Since the amount of state that you can "capture" in this way is not limited, then - by definition - the std::function must allocate memory from the heap upon construction, and deallocate it, copy it and move it at appropriate times. Again, it is this extra "state" that gets copied, not the code.
Let's review: each std::function needs to be able to store at least a pointer to executable code, and 0 or more bytes of extra captured state. If there is no captured state, a std::function is essentially the same as a function pointer (although in practice, std::functions are usually implemented polymorphically and have other stuff in there.)
Some (most) implementations of std::function that I'm aware of employ an optimization that is called "Small Object Optimization". In these implementations, in addition to the space for the pointer to code, the std::function object has some more (fixed amount of) space inside its instance (i.e. as a member of its class, as opposed to somewhere else on the heap) and will use that area if the total number of bytes of the captured state would fit in there. This eliminates the heap allocation, which is important in some use cases and would balance out the additional memory used (when there is no or little state to capture.)
I think the information in regarding the exceptions share some light:
Does not throw if other's target is a function pointer or a std::reference_wrapper, otherwise may throw std::bad_alloc or any exception thrown by the constructor used to copy or move the stored callable object. CppReference
This seems to imply that every copy of the std::function copies the contained callable as well. For example, in case your function contains a lambda with a vector, that lambda and by result vector gets copied. The actual machine code that is linked to it, stays in the read-only part of your executable and won't be copied.
An update from the c++20 standard draft: 20.14.16.2.1 Constructors and destructor[func.wrap.func.con]
function(const function& f);
Postconditions: !*this if !f; otherwise, *this targets a copy off.target().
Throws: Nothing iff’s target is a specialization ofreference_wrapperor
a function pointer. Otherwise, may throwbad_allocor any exception
thrown by the copy constructor of the stored callable object.
[Note:
Implementations should avoid the use of dynamically allocated memory
for small callable objects for example, where f’s target is an object holding only a pointer or reference to an object and a member function pointer. — end note]
It seems that std::function does only manage one callable.
If copied, what happens to code is specified by the callable itself.
In a function pointer case, only a function pointer needs to be copied.
In a lambda or custom callable case this would be determined by the implementation of the copy of lambdas or any custom callable class.
These latter 2 typically can hold members of their own, outside of the reference to code. Therefore some space must be allocated by std::function to accomodate these cases. This is however misleading as it could seem std::function as allocating space for code. The management of instruction code seems to be done by the callable however this is done internally there.
In this context default behavior of typically used callables (like lambdas) when copied seems far more interesting for the intended question, but does seem to strech the posed question too far out of the bounds of the context of std::function.
I therefore would consider this question as solved as posed and deepen my knowledge about how lamdas are implemented especially in regards to how they are compiled and the compiled code referenced.
I have seen many instances where people have advised against using std::function<> because it is a heavyweight mechanism. Could someone please explain why that is so?
std::function is a type erasure class.
It takes whatever it is constructed from, and erases everything except:
Invoke with the signature in question (with possible implicit casting)
Destroy
Copy
Cast back to exact original type
and possibly
Move
This involves some overhead. A typical decent-quality std::function will have small object optimization (like small string optimization), avoiding a heap allocation when the amount of memory used is small.
A function pointer will fit in there.
However, there is still overhead. If you initialize a std::function with a compatible function pointer, instead of directly calling the function pointer in question, you do a virtual function table lookup, or invoke some other function, which then invokes the function pointer.
With a vtable implementation, that is a possible cache miss, an instruction cache miss, then another instruction cache miss. With a function pointer, the pointer is probably stored locally, and it is called directly, resulting on one possible instruction cache miss.
On top of this, in practice compilers understand function pointers better than std::functions: a number of compilers can figure out that the pointer is constant value during inlining or whole program optimization. I have never seen one that pulls that off with std::function.
For larger objects (say larger than sizeof(std::string) in one implementation), a heap allocation is also done by the std::function. This is another cost. For function pointers and reference wrappers, SOO is guaranteed by the standard.
Directly storing the lambda without storing it in a std::function is even better than a function pointer: in that case, the code being run is implicit in the type of the lambda. This makes it trivial for code to work out what is going to happen when it is called, and inlining easy for the compiler.
Only do type erasure when you need to.
Under the hood, std::function typically uses type erasure (one simplified explanation for how it may be implemented is here). The cost of storing your function object inside the std::function object may involve a heap allocation. The cost of invoking your function object is typically an indirection through a pointer plus a virtual function call. Also, while compilers are getting better at this, the virtual function call usually inhibits inlining of your function.
That being said, I recommend using std::function unless you know via measurements that the cost is too high (typically when you cannot afford heap allocations, your function will be called many times in a place that requires very low latency, etc.), as it is better to write straightforward code than to prematurely optimize.
Depending of the implementation, std::function will add some overhead due to the use of type easure. They have been some other implementation such as Don Clugston's fast delegate, with a C++11 implementation here. Please note that it uses UB to make the fastest possible delegate, but is still extremely portable.
If you want type erasure it's the right tool for the job and almost certainly not your bottleneck and not something you could write faster anyway.
However sometimes it can be all to tempting to use type erasure when it really isn't required. That's where to draw the line. For example if all you want to do is keep hold of a lambda locally then it's probably not the right tool and you should just use:
auto l = [](){};
Likewise for function pointers you don't plan to type erase - just use a function pointer type.
You also don't need type erasure for templates from <algorithm> or your own equivalents because there's simply no need for heterogenous functor types to coexist.
It's not so.
To put it simply, it's not too heavyweight unless you profiled your program and showed that it is too heavyweight. Since evidently you did not (otherwise you would know the answer to this question), we can safely conclude that it is in fact not too heavyweight at all.
You should always profile, before concluding that it's too slow.
If you are passing a large object to a function, say a class containing a large array, is it always better to pass by reference? The idea would be to construct the function so:
template<class T> double foo(T& t){...}
ADDITION AFTER FIRST POST:
If I wanted the function to be non-modifying, I would use a const reference.
I could then call the function simply by passing the objects to it:
T large_data = T(1000000);
f(large_data);
This is the basic idea behind passing an object into a function by reference (with const for immutable objects): you don't want to pass the underlying (large amount of) data and you don't want the messiness (memory management issues, -> and dereference) of a pointer.
Generally in C++ for every custom type is better to pass by reference or by pointer. Otherwise, except performance, you could experience problems if your object requires custom copy constructor (and you maybe don't have it implemented, but compiler generated one will do only shallow copy). Also, slicing could happen, etc...
I have a collection (currently boost::ptr_vector) of objects (lets call this vec) that needs to be passed to a few functors. I want all of the functors to have a reference/pointer to the same vec which is essentially a cache so that each functor has the same data cache. There are three ways that I can think of doing this:
Passing a boost::ptr_vector<object>& to the constructor of Functor and having a boost::ptr_vector<object>& member in the Functor class
Passing a boost::ptr_vector<object>* to the constructor of Functor and having a boost::ptr_vector<object>* member in the Functor class
avoid the use of boost::ptr_vector and directly pass an array (object*) to the constructor
I have tried to use method 3, but have been told constantly that I should use a vector instead of a raw pointer. So, I tried method 2 but this added latency to my program due to the extra level of indirection added by the pointer. I am using method 1 at the moment, however I may need to reassign the cache during the lifetime of the functor (as the data cache may change) so this may not be an appropriate alternative.
Which I don't fully understand. I assume somewhere along the way the functor is being copied (although these are all stored in a ptr_vector themselves).
Is method 3 the best for my case? method 2, is too slow (latency is very crucial), and as for method 1, I have been advised time and again to use vectors instead.
Any advice is much appreciated
A reference in C++ can only be initialized ('bound') to a variable.
After that point, a reference can not be "reseated" (made to refer to a different variable) during it's lifetime.
This is why a default copy constructor could conceivably be generated, but never the assignment operator, since that would require the reference to be 'changed'.
My recommended approach here is to use a smart pointer instead of a reference.
std::unique_ptr (simplest, takes care of allocation/deallocation)
std::shared_ptr (more involved, allows sharing of the ownership)
In this case:
std::shared_ptr<boost::ptr_vector<object> > m_coll;
would seem to be a good fit