Ad

Returning A Range Of References To A Std::vector>

- 1 answer

I have an abstract base class T and another class holding a vector of unique pointers to T. The class should support two function returning references to the entries. One of them should provide read-access, the other one should be able to modify the values in the unique_ptrs but not the pointers:

class A {
  private:
    std::vector<std::unique_ptr<T>> data;
  public:
    auto access() -> RefRange<T>;
    auto const_access() -> ConstRefRange<T>;
};

The ranges should satisfy the requirements of a std::random_access_range. How can I do this without allocating additional memory in C++17 (boost is available)?

Ad

Answer

If you have boost, much of this is done by the range adaptor indirected

class A {
  private:
    static auto add_const(T & t) -> const T & { return t; }
    std::vector<std::unique_ptr<T>> data;
    using indirected = boost::adaptors::indirected;
    using transformed = boost::adaptors::transformed;
  public:
    auto access() { return data | indirected; }
    auto const_access() const { return data | indirected | transformed(add_const); }
};

Or with std::views::transform in C++20

class A {
  private:
    static auto indirect(const std::unique_ptr<T> & ptr) -> T & { return *ptr; }
    static auto add_const(T & t) -> const T & { return t; }
    std::vector<std::unique_ptr<T>> data;
    using transform = std::views::transform;
  public:
    auto access() { return data | transform(indirect); }
    auto const_access() const { return data | transform(indirect) | transform(add_const); }
};

If you have <experimental/propagate_const>, I'd use that instead of whichever transform(add_const).

class A {
  private:
    std::vector<std::experimental::propagate_const<std::unique_ptr<T>>> data;
    using indirected = boost::adaptors::indirected;
  public:
    auto access() { return data | indirected; }
    auto const_access() const { return data | indirected; }
};
Ad
source: stackoverflow.com
Ad