这是indexloc提供的服务,不要输入任何密码
Skip to content

[inplace_function] Const-callability means thread-safety #158

@Quuxplusone

Description

@Quuxplusone

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 only operator() (non-const)

  • inplace_function<R(As...) const> is constructible only from const-callable lambdas, and provides only operator() 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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions