The example on the page of std::ref
/std::cref
shows the use of std::ref
/std::cref
to pass arguments to std::bind
in a way that looks like std::bind
is taking arguments by reference, when in reality it takes them all by value.
Looking at that example only, I could also be ignorant about the existence of std::reference_wrapper
, and std::ref
would just be a function that allows the behavior exhibited by the linked example.
That's what I mean by std::ref
works in the title of the question and also in the following.
Mostly for fun I've tried implementing std::ref
myself, and I came up with this:
template<typename T>
struct ref_wrapper {
ref_wrapper(T& t) : ref(t) {}
T& ref;
operator T&() const {
return ref;
}
};
template<typename T>
ref_wrapper<T> ref(T& t) {
return ref_wrapper{t}; // Ooops
}
template<typename T>
ref_wrapper<const T> cref(const T& t) {
return ref_wrapper{t}; // Ooops
}
where on the lines marked as // Ooops
I have mistakely made use of CTAD because I was compiling with -std=c++17
. By changing ref_wrapper
to ref_wrapper<T>
and ref_wrapper<const T>
in the two cases corrects this.
Then I've had a peek into /usr/include/c++/10.2.0/bits/refwrap.h
.
On the one hand, I see that my implementation of ref
/cref
closely resembles that of std::ref
/std::cref
.
On the other hand, I see that std::reference_wrapper
is around 60 lines long! There's a lot of stuff in there, including noexcept
, macros, copy ctor, copy operator=
, get
.
I think most of that is not relevant to the use of std::reference_wrapper
only as a slave to std::ref
, but there's something which could be relevant, such as constructor taking a universal reference.
So my question is: what are the parts of std::reference_wrapper
necessary and sufficients for std::ref
to work, with respect to my skinny attempt?
I've just realized that there's a possible implementation of std::reference_wrapper
on cppreference (which is less noisy than the one from GCC). Even here, however, there are things I don't undertand the reason of, such as operator()
.