My question concerns the line of code below marked with the // WHY??? comment.
Below is a toy example of some code I was expecting to break: a std::function variable is assigned a function pointer whose parameters almost match, but differ in const and &. It didn't break. I've figured out why it works -- there's a copy constructor call added by the compiler that I didn't expect.
My question is: why does C++ allow this case? What is the use-case that made the C++ committee decide this should work (as opposed to the compiler rejecting this assignment)?
#include <memory>
#include <functional>
#include <iostream>
class Thing {
public:
Thing(int count) : count_(count) {}
int count_;
};
typedef std::function<void(const Thing&)> ConstByRefFunction;
void DoThingByValue(Thing event) { event.count_ += 5; }
int main() {
Thing thing(95);
ConstByRefFunction func = DoThingByValue; // WHY???
// The following line copies thing even though anyone looking at
// the signature of ConstByRefFunction would expect it not to copy.
func(thing);
std::cout << thing.count_ << std::endl; // still 95
return 0;
}
std::functionsatisfies the requirements of CopyConstructible and CopyAssignable. If it stored a reference, then it would not be CopyConstructible.std::functionthat says it takes by const reference.std::functiontakes byconst&then it shouldn't be changing the passed in parameter. I think that is why the assignment is valid since the copy follows the same semantics.Thing, compiler (at least g++) complains exactly about line with //WHY as conversion from ‘void(Thing)’ to non-scalar type ‘ConstByRefFunction’ {aka ‘std::function<void(const Thing&)>’} requested