Search code examples
c++vectorshared-ptrsmart-pointers

Exposing a vector of shared_pointers without giving ownership


I have a simple class containing a vector of shared pointers:

class Bar {
public:
  /* stuff */
private:
  std::vector<std::shared_ptr<Foo>> foos;
};

I wish to expose my foos through a getFoos() function, that would not share the ownership of the objects. One way to do so would be:

std::vector<std::reference_wrapper<Foo>> Bar::getFoos() const {
  std::vector<std::reference_wrapper<Foo>> fooRefs;
  fooRefs.reserve(foos.size());
  for (auto& ptr : foos) {
    fooRefs.push_back(std::ref(*ptr));
  }
  return fooRefs;
}

but that's pretty ugly. Also, I'll most likely need to cache the results since this function gets called pretty often. More complexity, more ugliness.

Is there a cleaner/better way to deal with this issue?


Solution

  • I would expose the Foo by index and also give the possibility to obtain iterators to them

    class Bar {
    public:
      class FooIt {
        // Add typedefs for category etc
        std::vector<std::shared_ptr<Foo>>::iterator it; // maybe template on this to easily provide the const overload too
      public:
        Foo& operator*() const {
          return **it;
        }
        // write Functions to expose ++ etc of it
      };
    
      FooIt begin() {
        return FooIt{begin(foos)};
      }
    
      FooIt end() { 
        retuen FooIt{end(foos)};
      }
      // Enables ranged for over Bar, only do if that makes sense for your Bar
    
      Foo& getFoo(size_t index) { // maybe even operator [] if appropriate
        return foos[index];
      }
    };
    

    Of course this is much boilerplate. But actually you can write the FooIt in a general, templated version if you have this problem at multiple places.