A const std::reference_wrapper works similar to a reference, or a T* const (demo):
#include <functional>
struct S {
    void operator()() { i++; }
    int i = 0;
};
int main() {
    S s;
    const std::reference_wrapper<S> r = s;
    // now s.i == 0
    r();
    // now s.i == 1
    S* const p = &s;
    // now s.i == 1
    (*p)();
    // now s.i == 2
}
r is const, and std::reference_wrapper::operator() is a const method, thus we can call it, which in turn modifies the pointee. But, this operator() is a standard library function, thus [res.on.data.races]#3 quoted from the C++23 standard applies to it:
A C++ standard library function shall not directly or indirectly modify objects ([intro.multithread]) accessible by threads other than the current thread unless the objects are accessed directly or indirectly via the function's non-const arguments, including
this.
Does std::reference_wrapper violate this rule?
Problem is that std::reference_wrapper<S> does not store a value, but reference. std::reference_wrapper<S> is not changed, but S s; is changed.
It is like holding a constant pointer to modifiable object.
So everything is ok. r remains unchanged. s is updated.
So const version of function call operator is called and this member function call function call operator on s which is not const.
Documentation clearly states that operator() for is const
template< class... ArgTypes >
std::invoke_result_t<T&, ArgTypes...>
    operator() ( ArgTypes&&... args ) const noexcept(/* see below */);
                        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