0

In the C++ 20 Standard the constructor of the class template std::reference_wrapper is a template.

template<class U>
constexpr reference_wrapper(U&&) noexcept(see below ); 

while the assignment operator is not a template

constexpr reference_wrapper& operator=(const reference_wrapper& x) noexcept;

What is the reason that this difference (template and non-template) between these special member functions exists?

On the other hand, I tried the following progarm using Visual C++ 2019.

#include <iostream>
#include <functional>

struct A
{
    void f() const { std::cout << "A::f()\n"; }
    virtual void g() const { std::cout << "A::g()\n"; }
};

struct B : A
{
    void f() const { std::cout << "B::f()\n"; }
    void g() const override { std::cout << "B::g()\n"; }
};

int main()
{
    B b;

    std::reference_wrapper<A> r( b );

    r.get().f();
    r.get().g();


    r = std::reference_wrapper<B>( b );
}

and the compiler did not issue an error message relative to the assignment operator.

Is it a bug of the compiler or have I missed something?

1 Answer 1

4

If std::reference_wrapper<T> had a single constructor accepting T&, then it would lead to bugs like std::reference_wrapper<const T> being able to bind to temporaries of type T. So, originally there were two constructors (other than the copy constructor): one taking T&, and another taking T&&, which was defined as deleted, ensuring that a compile error would occur.

However, it was pointed out that this is not really what we want: it would be better if std::reference_wrapper<T> would have no constructor at all that accepts an rvalue of type T, as opposed to a deleted constructor. This is LWG 2993. (You'll notice that this issue is mentioned at the bottom of the cppreference page.) Thus, the constructor was changed to a template that is SFINAE-disabled as appropriate.

Once these issues are solved for the constructor, the assignment operator only needs to have a single overload taking reference_wrapper. The conversion issues will be handled by the constructor logic when the compiler forms the implicit conversion sequence.

Sign up to request clarification or add additional context in comments.

4 Comments

But the standard does not allow accepting by the constructor an object of the type std::reference_wrapper.
@VladfromMoscow there is a copy constructor, is there not?
The copy constructor is also a non-template constructor.
@VladfromMoscow yes, there is a copy constructor and a template converting constructor, but I don't understand where you're going with this.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.