So, we are working on a C++ math application designed for distributed memory systems (so typically some supercomputer with homogeneous nodes) and I have the following problem:
Currently, we have a implementation of a distributed vector (in the math sense), which is a tree-like structure of our second local vector class: pretty much being just a std::vector with some operations on top. Both vectors are template classes and inherit from some abstract math vector interface. I wrote some quick code below.
template<typenname T>
class AbstractVector {
public:
T one_norm() const = 0;
...
}
template<typename T>
class LocalVector : public AbstractVector<T> {
private:
std::vector<T> storage;
...
public:
T one_norm() const;
...
}
template<typename T>
class DistributedVector : AbstractVector<T> {
private:
AbstractVector<T>* children;
...
public:
T one_norm() const;
...
}
Now this all works well until I want to save certain attributes associated with the entries of my numerical vectors - so I would have e.g. one numerical vector and one that does not allow for computations at all but is just sort-of a storage of something.
Since the distributed math vector directly implements both, its storage model and the abstract vector interface, I cannot just use it for some random type since most of the numerical operations would not be defined for that type (e.g. "+" and "-" and "*") and would also not make any sense. Best example might even be a DistributedVector<bool> which does not make sense in the math vector but is totally reasonable else.
I think the design flaw is exactly that the concept of the distributed storage and its math implementation are not separated from each other (like in the local vector where I have the storage std::vector and the wrapper around it).
My question is - what is the nicest way to do better?
My first idea:
Ok, separate the concerns, have some kind of a distributed version of the std::vector and use that in the distributed math-vector as storage. The distributed math-vector would thus just be some kind of wrapper - or rather a decorator (the design pattern that came to my mind here) and provide the additional functionality that a math distributed vector would need. Here I am not sure - should I let the math distributed vector inherit from both - the distributed storage and the abstract vector interface? Or is the nicer way similar to the local vector where the distributed math vector just owns a distributed storage and works on that?
Maybe there is also better design that I am missing, this is why I am asking here :)
I don't have any functional restrictions on the C++ standard I am using - but I my refactoring should not break everything possibly.
Thanks in advance!