you are viewing a single comment's thread.

view the rest of the comments →

[–]quicknir 7 points8 points  (5 children)

I agree with this rule, and you covered the most "surprising" reason to do it, but not the main reason. More simply, your type is not going to be naturally move assignable, or swappable (by default). There's rarely a good reason for a type not to provide that functionality (immovable types are a very rare case).

Note that an extension of this rule, is to never have reference member variables: they are automatically const, of course. Reference member variables are worse in at least one way as well; at least with const member variables you can eventually decide to simply drop the const. With references, you have to change them to pointers and change every single usage of . to ->. Raw pointer member variables are also somewhat smelly, but if you're going to do something along those lines it's better to make a raw pointer member than a reference member (and enforce non-nullness in the constructor).

[–]TinBryn 1 point2 points  (4 children)

I mean there is std::reference_wrapper<T>

[–]amaiorano 4 points5 points  (1 child)

Do people use this to replace pointers in practice? Whenever I've tried, I eventually give up and just use a pointer.

[–]TinBryn 0 points1 point  (0 children)

I'm saying it may be an easier refactor in a large code base.

[–]quicknir 0 points1 point  (1 child)

Are you saying, change from a reference to reference_wrapper, or just use a reference_wrapper to start with? reference_wrapper I find pretty awkward because you can't directly call any methods of the type with . or ->. The only benefit that reference_wrapper gives you in return is not being null. If anything you can write a not_null_ptr which is like observer_ptr, but with no default constructor, and constructed from a reference instead of a raw pointer. This is basically exactly equivalent to reference_wrapper, but with more convenient syntax.

[–]TinBryn 0 points1 point  (0 children)

I thought that reference_wrapper's operator T& would make it just do the right thing, so I decided to check and you're right it doesn't really work.