在不提供所有权的情况下公开 shared_pointers 的矢量

Exposing a vector of shared_pointers without giving ownership

我有一个包含共享指针向量的简单 class:

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

我希望通过 getFoos() 函数公开我的 foos,该函数不会共享对象的所有权。一种方法是:

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;
}

但这很丑陋。另外,我很可能需要缓存结果,因为这个函数经常被调用。更复杂,更丑陋。

是否有 cleaner/better 方法来处理这个问题?

可能是范围视图 range-v3:

class Bar {
public:
  /* stuff */

     auto get_foos() const { return foos | ranges::views::indirect; }
private:
  std::vector<std::shared_pointer<Foo>> foos;
};

与您的 std::vector<reference_wrapper> 类似,但没有额外的矢量。

views::indirect Given a source range of readable values (e.g. pointers or iterators), return a new view that is the result of dereferencing each.

也可以用 view::transform 来完成。

我会通过索引公开 Foo 并提供获得迭代器的可能性

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];
  }
};

当然这是很多样板文件。但实际上,如果您在多个地方遇到此问题,您可以将 FooIt 编写为通用的模板版本。