I'm seeing code that looks like this:
template<class Function>
void MyFunc(Function&& function) { function(...); }
What's the advantage of && here, as opposed to just copying the function by value? For reference, I'm using C++14.
The problem comes from avoiding copies.
Imagine this:
auto lambda = [ptr = std::make_unique<int>(0)]() mutable {
std::cout << *ptr;
ptr = std::make_unique<int>(*ptr + 1); // why not?
};
MyFunc(lambda); // use it normally
MyFunc([]{ std::cout << " end"; }); // use by using a temporary lambda
lambda() // just call the function after that
If the signature is MyFunc(Function f), it would require a std::move and the lambda would not be useable after the call.
If the signature is MyFunc(Function const& f), it would not work since the lambda is mutable.
If it was MyFunc(Function& f) then the temporary would not work.
You're basically left with MyFunc(Function&& f).
The real question however is "Do I need to support all these cases?"
I would tell: most of the time no. Most of the time, receiving the lambda by value is the simplest and support almost every cases. This is the way the STL went.
Why? Because perfect forwarding of function objects is really hard to get perfect, and you cannot call the function multiple times in most of the cases in a pefectly generic way. I would perfect forward a function only if I want to wrap it, want to completely avoid copies and I expect function objects that are ref qualified to temporaries.
When learning C++, one of the first functions one gets for learning the concept of a function is something like
int add(int a, int b)
{
return a+b;
}
Now I was wondering: Should I use the const-keyword here, or rather not, resulting in
int add(const int a, const int b)
{
return a+b;
}
But would that make sense? Would it speed my program up, do some other important stuff, or just increase confusion?
From the caller's perspective, both the first and the second form are the same.
Since the integers are passed by value, even if the function modifies a and b, the modified values are copies of the original and won't be visible to the caller.
However, from the function implementer's perspective there's a difference. In fact, in the second form:
int add(const int a, const int b)
you will get a compiler error if you try to modify the values of a and b inside the function's body, as they are marked as const.
Instead, you can change those values if you omit the const.
Again, those modifications will not be visible to the caller.
If you are actually struggling with correctness bugs in your codebase where const would have helped, then add const.
That said, there are related issues that you should consider. Top-level qualifiers of function parameters aren't part of the function type, so your function type is still just int(int, int). (The qualifiers only affect the parameter variables in the function definition.) That means that any declaration of the function also ignores qualifiers, so int add(int, int) and int add(const int, int) and int add(int, const int) all declare the same function. So you have to decide on a policy for how you write header files. And now you have three essential positions you can take:
Always qualify in both declaration and definition. The upside is that this perhaps keeps code looking "consistent" (think copy/pasting when creating implementations). The downside is that the qualifiers have nothing to do with the interface, and are not at all enforcible (you can change the definition later!), so at best it's noise, at worst it's wrong.
Qualify in the definition, but not in the other declarations. The upside is that this communicates the interface correctly and you still get const checking in the definition. The downside is that some people might be confused by the discrepancies in spelling. (Just like people may be confused that a static constexpr T foo; class member can be defined with const T C::foo;.)
Don't qualify either. The upside is that it's consistent, clean, easy to remember and minimal. The downside is that you're missing out on correctness checks in your definition.
There's no right answer. If you're the codebase owner or project lead, you should decide based on what the biggest problems in your codebase and team are. (My personal position is to stick with (3) until you have a good reason to change.)
Using int add(const int a, const int b) means that you cannot modify the input parameters within the function body.
Perhaps the compiler can make some optimisations based on that, so it ought therefore to be never slower than the non-const equivalent. But I have never observed this effect in practice.
Passing const parameters can also increase the stability of your code base, particularly in a collaborative project.
All this said though, I find it too verbose, rather unnecessary, and would use int add(int a, int b). Very occasionally, for particularly long functions, I exploit the fact that you can declare the function with non-const parameters, and define it with the parameters const.
I feel like everyone is dancing around this part of the answer...
It's true that using const will keep the function from modifying the value of your int a & b while inside the function. This can be extremely useful, so use it as you wish, of the compiler allows it. But, the function caller will never know about any changes to a & b once the function finishes. So even if a & b are changed, no one except the defined function will know their updated values.
int funcB(int a, int b)
{
a = a+1;
b = b*b;
return a+b;
}
void funcA()
{
int s = 5;
int t = 6;
int result = funcB(s, t);
printf("%f + %f = %f", s,t, result);
}
funcA prints: "5 + 6 = 42"
Const protection is often used when passing values by reference, ie:
int function(const int &a, const int &b) {}
This passes a reference of a and b to the function (ie, does not make copies of a and b but passes only a memory address of that variable, aka: the handle). When passing a variable by reference, any changes made to the variable are remembered outside the scope of the function and can change the way your program runs. This is generally undesired behavior.
So if you rework funcB from above and pass by reference:
int funcB(int &a, int &b)
{
a = a+1;
b = b*b;
return a+b;
}
funcA prints: "6 + 36 = 42"
If you add const correctness to funcB:
int funcB(const int &a, const int &b)
{
a = a+1;
b = b*b;
return a+b;
}
I don't think the compiler will let you even do this since you would be explicitly trying to modify values that you've protected via const.
Another time when it may be really important to use const is when you're passing by pointer, instead of reference or copy...
int funcB(int *a, int *b)
{
a = a+1;
b = b*b;
return a+b;
}
Unless you're a pointer expert, avoid passing pointers without const pretention. This func will likely attempt to iterate the index of your pointer arrays and you'd open yourself up to run time errors related to out of bound memory. You could accidently see memory from an entirely different program... but probably not.
Lastly, since you're just passing int, there's no practical need to pass by reference (which is done often to keep from adding complex data into memory because each non-reference or non-pointer pass to functions copies the value into memory for the life of the function being called) since the memory footprint of int is so small. Unless, you're working with specialized hardware that has extremely limited memory, then it may be useful; this won't apply to most standard computers and desktops made within the past 20 years, or smart phones.
int add(const int a, const int b)
{
return a+b;
}
Here const in used so that the function does not modify the original values of a and b by any chance.
In the above example it does not make sense. But if it would have been an example like
int add(const int *a, const int *b)
{
//*a = 10; //This will throw error.
return a+b;
}
In functions where objects,arrays or such data types are passed its a good approach to use const to avoid mutation of original data structure.
If you want to be truly const correct, then you should add it, but in reality all it will do is make you type and read more.
Nothing will go faster, and while it could mean that your variables go into another location in memory, it's unlikely to on most modern machines.
What it will stop you doing is accidentally assigning them values, but as they're local to the function, it's relatively unimportant. What would matter is if they were references, as this demonstrates your intent to the caller to not change them.
You can use const there if you like.
It is unlikely to speed up your program because any reasonable compiler can already see that no code path alters the value of a or b and make any optimisations it needs.
a and b are int, which are passed by value so making them const has no impact on the users of this function.
The only possible advantage is where your function is long and more complex and you want to avoid possible programming errors where the original values of a or b are changed during the function.
If you will use const then you cannot modify the value of a,b. Thats why we don't use const.
The primary purpose of constness is to provide documentation and prevent programming mistakes. Const allows you to make it clear to yourself and others that something should not be changed. Moreover, it has the added benefit that anything that you declare const will in fact remain const short of the use of forceful methods. It's particularly useful to declare reference parameters to functions as const references:
bool SomeFunction (const myObj& obj);
Here, a myObj object is passed by reference into SomeFunction. For safety's sake, const is used to ensure that SomeFunction cannot change the object--after all, it's just supposed to make sure that the object is in a valid state. This can prevent silly programming mistakes that might otherwise result in damaging the object (for instance, by setting a field of the class for testing purposes, which might result in the field's never being reset). Moreover, by declaring the argument const, users of the function can be sure that their object will not be changed and not need to worry about the possible side effects of making the function call.
moreover, The reason is that const for the parameter only applies locally within the function, since it is working on a copy of the data. This means the function signature is really the same anyways. It's probably bad style to do this a lot though. I personally tend to not use const except for reference and pointer parameters.
as a law of thumb we are advised to use const as much as possible because we get a great help from the compiler so whenever we try to change a constant the mistake will be caught by the compiler; it's a good thing avoiding being caught in error-prones.
the second thing: a and b passed by value so they are created as local constants But as long as they are not changeable why we need copies??
the good thing is to pass a const reference which means never change parameters and avoid copies (by value):
int add(const int& a, const int& b) // now there are no copies of a and b in addition we cannot modify a and be
{
return a+b;
}
I'm trying to make a function that accepts a shared pointer to some functor. With manually crafted functors there're no problems, but with lambda there are. I know that I can't use decltype with lambda - every new lambda declaration creates a new type. Right now I'm writing:
auto lambda = [](int a, float b)->int
{
return 42;
};
using LambdaType = decltype(lambda);
shared_ptr<LambdaType> ptr{ new LambdaType{ lambda } };
It works, but looks ugly. Moreover there's a copy constructor call! Is there any way to simplify?
You could use std::function as type.
Lambdas are merely auto written invokable objects to make simple code simple. It you want something beyond their default automatic storage behavior, write the type they write yourself.
It is illegal to have a lambda type in an unevaluated context. In an evaluated context, it creates a lambda in automatic storage. You want it on the free store. This requires at least logically a copy.
A horrible hack involving violating the unevaluated context rule, sizeof/alignof, aligned_storage_t, placement new, possibly unbounded compile time recursion (or maybe one with a static_assert), returning pointers to local variables, and the aliasing constructor of shared ptr, and requiring callers to write insane code might avoid calling the copy/move. But it is a bad idea, and simply using invokable objects is easier.
Of course, accepting the copy/move makes it trivial. But at that point, just use std::function unless you need something like varargs.
You state you do not want to force users to use std::function; but std::function would implicitly convert a compatible lambda into itself.
If you are willing to accept a copy, we can do this:
template<class T>
std::shared_ptr<std::decay_t<T>>
auto_shared( T&& t ) {
return std::make_shared<std::decay_t<T>>(std::forward<T>(t));
}
then auto ptr = auto_shared( [x=0]()mutable{ return x++; } ); is a non-type-erased shared pointer to a counting lambda. The lambda is copied (well, moved) into the shared storage.
If you want to avoid that copy, the client can write a manual function object and call make_shared<X>(ctor_args) on it.
There is no reasonable way to separate a lambdas type from its construction in C++ at this point.
if you catch something in lambda, it becomes algorithmically same as std::function, so use it freely. Also, std::function implements captured values memory management, so using std::shared_ptr on top of it is not required.
If you catch nothing, lambda is convertible to simple function pointer:
int(*ptr)(int,int) = [](int a, int b) -> int {
return a+b;
};
Functions are allocated statically and definitely shouldn't be deleted. So, you don't actually need std::shared_ptr
For the struct:
struct A {
int var = 10;
void check() {
std::cout << "var is " << var << std::endl;
}
};
Say I create a std::function object of A::check(), using a dynamically allocated a object:
auto a_ptr = std::make_unique<A>();
std::function<void()> f = std::bind(&A::check, a_ptr.get());
//...later/elsewhere...
f();
It would be nice for safety if I could test f to see if the bound A object is still alive. Is it possible to retrieve that information from f directly? Assume a_ptr is not accessible from the call point, so I can't test against a_ptr directly. Using std::function's operator bool, or testing f against nullptr don't work.
So you basically want your function object to test for the existence of the A instance managed by a_ptr, i see 3 ways of doing this with the current c++ std features.
-- Lambda with a reference to the unique_ptr
auto a_ptr = std::make_unique<A>();
std::function<void()> f = [&] { if (a_ptr) a_ptr->check(); };
//...later/elsewhere...
f();
This requires that the pointer is still alive anytime the function object is alive.
-- Lambda with a copy of the shared_ptr
auto a_ptr = std::make_shared<A>();
std::function<void()> f = [=] { if (a_ptr) a_ptr->check(); };
//...later/elsewhere...
f();
Same thing but without requirements on the lifetime relationship at the expense of some additional performance cost which is mainly the copy of a shared pointer, probably totally worth the headache it saves in most cases (i'm going to be burned by the optimisation guys for this one).
-- Custom deleter in your smart pointer that resets your function
std::function<void()> f;
auto a_ptr = std::unique_ptr<A, std::function<void(A*)>>(new A, [&](A*){ f = nullptr;});
f = std::bind(&A::check, a_ptr.get());
//...later/elsewhere...
a_ptr.reset();
if (f)
f();
This requires that somehow your deleter can access the function to reset it, whether it is directly or through a storage system in your classes (containers of functions are a nice design imo).
You can also create more elaborated systems with your own primitives but that would lead you further away from the standard library. Ultimately you'll have to choose what's best in your situation mainly based on the lifespan and ownership relationships of your objects.
Well, this one is easy, use std::shared_ptr.
when you think about it , you basically want to ensure that some entity in you program is valid as long as something is using it.
In other words, you are looking for a shared_ptr.
Otherwise, the design looks a bit weird, if some single entity in your program is owning a_ptr, it should be the single owner of all the std::functions which uses this resource, which is not your intention. if that owner is not the owner of the std::function you are highly increasing the probability of segmentation faults, heap corruption and other stuff you don't want.
Imagine the following scenario:
typedef std::function<float(float)> A;
typedef float(*B)(float);
A foo();
void bar(B b);
You wish to do something along the lines of:
bar(foo());
Obviously this does not work. Mainly because A can contain a state and B is a function pointer. What if we know that A does not contain a state and we wish to somehow take it's "meaning" and put it into something that can be passed for a B?
Is it impossible?
If you can ensure that the callable object stored in A is a function pointer or a lambda with an empty capture list, you can simply get a function pointer in this way:
foo().target<B>();
In general, a std::function can "box" some closure (e.g. the value of some lambda function). And a closure contains both code and data (the closed values). So I believe that you cannot portably convert it to a naked function pointer. BTW, because conceptually closures are mixing code and data languages not providing them (like C) practically requires callbacks (i.e. the convention to pass every function pointer with some additional data, look into GTK for a concrete example).
Some implementation specific tricks might make a trampoline function on the stack (e.g. dynamically generate, perhaps with asmjit, some machine code containing a pointer to the closure, etc.). But this is not portable and system specific (in particular because the stack needs to be executable)
What if we know that A does not contain a state and we wish to somehow take it's "meaning" and put it into something that can be passed for a B?
Even that isn't sufficient. std::function provides a target() member function, that if you know the exact type of the underlying functor, you can get it back. So we can do, for instance:
void print(int i) { std::cout << i; }
std::function<void(int)> f = print;
auto ptr = f.target<void(*)(int)>(); // not null
(*ptr)(42); // works
However, even if our functor f doesn't contain state, that doesn't mean that its underlying type is precisely void(*)(int). It could be a completely different function pointer, in which case we wouldn't be able to pull it out:
int square(int i) { return i*i; }
f = square;
ptr = f.target<void(*)(int)>(); // nullptr!
Or it could be a lambda, in which case we wouldn't even be able to name the type, much less pull it out:
f = [](int i){ std::cout << i; }; // same as print, right?
ptr = f.target<void(*)(int)>(); // ... nope :'(
Basically, type erasure is really type erasure. If you need the original underlying type, that's likely indicative of a bad design.