Lightweight map proxy for class hierarchy

98 Views Asked by At

So recently I've been working on a library that is based around a hierarchy of classes as follows:

template <typename Base>
class Derived1 : public Base;

template <typename Base>
class Derived2 : public Base;

Fundamentally the problem I am trying to solve is given a common base class A I want a cheap (non-copying) conversion from a Derived1<A> to a Derived2<A>. Obviously this isn't going to work so well because any standard way of constructing a Derived2<A> from an A is going to involve a copy of the data in A - we can assume that this is a very expensive operation. The derived classes are essentially an interface for operating on the data contained in A

So the compromise I want to use is to create a proxy type for A, let's write Proxy<A>, which is a cheap object, so that I can convert a Derived<A> to a Derived2<Proxy<A>>. For example, if A = std::vector<int> then the proxy class I might use is a slice that just contains a pointer to the data and a size (or a pair of pointers, or iterators, whatever takes your fancy). (For simplicity let's assume that, once created, that the A never reallocates, which would invalidate my slices.) Now my Derived1<A> can implement a conversion operator to a Derived2<Slice<A>> and I have complete access to the data contained in A.

Now I want to play the same game with a std::map or std::unordered_map or some other kind of associative container type. The obvious choice of proxy type is, like the vector, a class that contains the begin and end iterators of the map. However, I have to re-implement the entire map interface on this proxy object. The other alternative is to have a proxy class that just contains a mutable reference to the container:

template <typename K, typename V>
class Proxy<std::map<K, V>>
{
    std::map<K, V>& map_ref;
}

This means I don't have to re-implement the interface but is deficient in other ways: for example, it cannot be default constructed (replacing reference with pointer slightly solves this problem, but still causes issues).

My question is: is there a sensible way to do this or some out of the box solution (in boost? I have looked but couldn't find such a thing.) I'm limited to C++14 but I welcome ideas that use c++17+ features for interest. I'm limited to C++14

0

There are 0 best solutions below