-
Notifications
You must be signed in to change notification settings - Fork 55
Description
Right now, inplace_function
permits
auto lam = [i=0]() mutable { return ++i; };
const stdext::inplace_function<int()> f(lam);
f();
That is, if I have a reference to a const inplace_function
, I can call its operator()
, which can mutate its internal state, even though I've promised not to modify it!
I believe we ought to follow the lead of Folly::Function, fu2::function, etc., and split inplace_function
into two kinds of specialization:
-
inplace_function<R(As...)>
is constructible from either const-callable or non-const-callable lambdas, and provides onlyoperator()
(non-const) -
inplace_function<R(As...) const>
is constructible only from const-callable lambdas, and provides onlyoperator() const
In this paradigm, you would not be permitted to write
int one(const inplace_function<int(int)>& f) {
return f(1) + f(2);
}
int two() {
auto mutlambda = [i = 0](int j) mutable { return i += j; };
return one(mutlambda);
}
The call to f(1)
would fail to compile because inplace_function<int(int)>::operator()(int)
is not const-qualified. Instead, you would have to write either
int one(const inplace_function<int(int) const>& f) {
return f(1) + f(2);
}
int two() {
int i = 0;
auto nonmutlambda = [&i](int j) { return i += j; };
return one(nonmutlambda);
}
or
int one(const inplace_function<int(int) const>& f) {
return f(1) + f(2);
}
int two() {
auto mutlambda = [i = 0](int j) mutable { return i += j; };
return one(std::ref(mutlambda));
}
or
int one(inplace_function<int(int)> f) {
return f(1) + f(2);
}
int two() {
auto mutlambda = [i = 0](int j) mutable { return i += j; };
return one(mutlambda);
}
depending on the semantics you want.