Reputation: 616
I often encounter situations where I need to store lists of non-owning pointers or references to base class objects. Of course, I could do
#include <initializer_list>
#include <list>
class Base {};
class Derived {};
class Container {
public:
void setObjects(const std::initializer_list<const Base *> objects); // Set objects_ member
private:
std::list<const Base *> objects_; // Should store Base and Derived objects
};
Using std::reference_wrapper
, I could also use
#include <initializer_list>
#include <list>
#include <functional> // for std::reference_wrapper
class Base {};
class Derived {};
class Container {
public:
void setObjects(const std::initializer_list<std::reference_wrapper<const Base> > objects); // Set objects_ member
private:
std::list<std::reference_wrapper<const Base> > objects_; // Should store Base and Derived objects
};
When I want to express the fact that an object (an instance of the Container
class in my case) cannot exist without other objects (instances of the Base
or Derived
class), I tend to prefer the second alternative. However, it feels quite verbose to me and I have rarely seen it in other code. Is there any good reason I should prefer one alternative over the other?
Upvotes: 4
Views: 1674
Reputation: 42838
I think correctness is more important than avoiding verboseness. At least for serious projects.
→ Always use reference_wrapper<T>
over T*
when nullptr
should not be valid.
If it's really too verbose, you can always define a type alias with a shorter name:
template<typename type> using ref = std::reference_wrapper<type>;
std::list<ref<const int>> objects_;
Or just a "tag" helper type to document the intent:
template<typename type> using not_null = type;
std::list<not_null<const int*>> objects_;
There's also the gsl::not_null<T*>
class in the Guidelines Support Library. For a related Q&A, see gsl::not_null<T*> vs. std::reference_wrapper<T> vs. T&.
Upvotes: 2