vendredi 8 janvier 2021

What is the crux of std::reference_wrapper implementation for the only purpose of makin std::ref work?

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().

Aucun commentaire:

Enregistrer un commentaire