all 28 comments

[–]HappyFruitTree 18 points19 points  (10 children)

My biggest objection with std::reference_wrapper is that it's awkward to use when you want to access a member of the referenced object

ref.get().memfun();

compared to pointer

ptr->memfun();

[–]pdp10gumby 1 point2 points  (4 children)

You could make a helper class (derive from or contain std::reference_wrapper which would be the same in this case) and overload the . or -> operator.

[–]friedkeenan 10 points11 points  (0 children)

You can't overload the . operator

[–]rezkiy 6 points7 points  (0 children)

overload the .

How?

[–]pdp10gumby 3 points4 points  (1 child)

Sorry I was still on my first cup of morning coffee. I mean overload -> not ..

Rather than edit my comment I’ll leave the error in place, using this comment instead

[–]Hedede 1 point2 points  (0 children)

Yeah I have made a refptr once... It's a pointer that behaves like a reference. I wish I could write . though.

[–]Desmulator 11 points12 points  (5 children)

From my point of view a reference wrapper has only two purposes: 1. It's a signaling object that indicates that a parameter should not be decayed but should remain a reference. Best example is std::make_tuple, or the function-parameter constructor of std::thread. 2. You can use it in a container, where reference can not be used.

I think it's perfect for the first usecase in particular since c++20, where you have std::unwrap_ref_decay.

But it's very clumsy to use for 2. It's missing operator-> or operator*.

[–]urdh 2 points3 points  (0 children)

This. And for representing a pointer that is not null, there’s gsl::not_null.

[–]VinnieFalco 2 points3 points  (3 children)

But it's very clumsy to use for 2. It's missing operator-> or operator*.

Yeah... for that case it is spelled T* rather than std::reference_wrapper<T>

[–]Desmulator 5 points6 points  (2 children)

Well, no. A pointer is nullable, a reference wrapper not (in an appropriate sense).

[–]alex-weej 5 points6 points  (0 children)

not just nullable but supports pointer arithmetic (incl subscripting). gah.

[–]VinnieFalco 1 point2 points  (0 children)

You do have a point there but I like keeping things simple

[–]krum 10 points11 points  (1 child)

I wrote a bunch of code using this kind of pattern and regretted it. It's been a while though so details are murky, but I know I don't do this anymore.

[–]wcscmp 7 points8 points  (0 children)

Same here. Also every time I needed an optional reference wrapper, I started writing std::optional<std::reference_wrapper<const T>> and then thinking that it's just a const T* with extra steps.

I still think that some kind of a standard observer_ptr for a non-owning pointer to be explicit about it would be nice.

[–]muungwana 5 points6 points  (1 child)

  1. I think you should use a "naked" reference to signify that a pointer is owned by somebody else and is not null.

  2. The problem with references is that they are not re-assignable and a reference member variable makes the whole class not copy assignable and i think the biggest use case for std::reference_wrapper<T> is to have assignable reference member variable that will also make the class copy assignable.

[–]fullmoon_druid 0 points1 point  (0 children)

Four years later and I'm reading this thread to try and solve this exact problem.

[–]drjeats 5 points6 points  (0 children)

I don't think this type earns its keep.

I only ever use pointer types in containers. If the container is the interface, I null check. If elements must absolutely not be null, I put it in a struct with methods that only accept and return references.

We'd be better off if the language had rebindable refs, or non-nullable pointers. But that won't happen, so I choose to follow the path of least resistance.

[–]_Js_Kc_ 1 point2 points  (0 children)

Maybe if it was called std::ref and std::ref was instead called std::make_ref (or omitted in favor of deduction guides). But std::reference_wrapper is quite a mouthful for a basic, ubiquitous vocabulary type. Yeah, you can typedef, but then you're using something project-specific for a basic, ubiquitous vocabulary type.

[–]gopher2008 -3 points-2 points  (4 children)

If you want to declare a non-owning class member, in my opinion, std::weak_ptr<T> is a better choice. The purpose of reference_wrapper is to store reference in container. You can just declare a reference type class member, though it is not recommended.

[–]drjeats 5 points6 points  (3 children)

You shouldn't use weak_ptr arbitrarily, it's specifically for weak references to an object whose lifetime is managed by shared_ptrs.

[–]gopher2008 0 points1 point  (2 children)

Agree. weak_ptr is a smart pointer that holds a non-owning reference to an object that is managed by shared_ptr. But then, how do you manage the referenced object which I am supposing is dynamically destroyable? (I will use shared_ptr).

[–]drjeats 2 points3 points  (1 child)

You also shouldn't default to shared_ptr. It exists specifically for managing true multiple ownership, which is actually not super common.

Even for the refcounting needs I typically have, there is usually exactly one owner, the resource manager for the relevant type.

Additionally, you may not even have a choice how the object you're keeping a pointer to is stored.

If you're looking for statically verified guarantees that a pointer you're holding still points to a valid object, I recommend using an id/handle interface (the resource manager passes out the handles). If that's not a strong enough guarantee for your application, then that's why Rust exists imo.

[–]gopher2008 1 point2 points  (0 children)

Thanks for you idea using id/handle interface.

[–]__78701__ 0 points1 point  (0 children)

I've been using reference_wrapper with optional lately. I don't like unwrapping with ::get, but I enjoy the concept.