I was surprised to find this code compiles:
#include <functional>
struct Callable {
void operator() () { count++; }
void operator() () const = delete;
int count = 0;
};
int main() {
const Callable counter;
// counter(); //error: use of deleted function 'void Callable::operator()() const'
std::function<void(void)> f = counter;
f();
const auto cf = f;
cf();
}
https://wandbox.org/permlink/FH3PoiYewklxmiXl
This will call the non-const call operator of Callable
. Comparatively, if you do const auto cf = counter; cf();
then it errors out as expected. So, why does const correctness not seem to be followed with std::function
?
const member functions may be invoked for const and non-const objects. non-const member functions can only be invoked for non-const objects. If a non-const member function is invoked on a const object, it is a compiler error.
If the thing you are returning by reference is logically part of your this object, independent of whether it is physically embedded within your this object, then a const method needs to return by const reference or by value, but not by non-const reference.
Const member functions in C++ To make a member function constant, the keyword “const” is appended to the function prototype and also to the function definition header. Like member functions and member function arguments, the objects of a class can also be declared as const.
If it is small, like 3-5 CPU instructions then yes std::function will make it slower, because std::function is not inlined into outer calling code. You should use only lambda and pass lambda as template parameter to other functions, lambdas are inlined into calling code.
std::function
adds a layer of indirection, and this layer of indirection does not pass through const
ness to the callable.
I'm not really sure why this is — probably because std::function
takes a copy of the callable and has no need to keep the copy const
(in fact this might break assignment semantics) — I'm also not really sure why you'd need it to.
(Of course, directly invoking operator()
on an object of a type that you just so happened to call Callable
and declared as const
will require a const
context, as it would with any other object.)
Best practice is to give the callable a const
operator()
and leave it at that.
tl;dr: true, but not a bug, and doesn't matter
You are correct to find this weird. The call operator of std::function
is marked const
but the const
ness is not propagated when the target object is actually invoked. The proposal p0045r1 seems to remedy this by making the call operator of std::function
non-const but allowing the following syntax:
std::function<return_type(arg_type) const>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With