I have a design question around a problem I'm trying to solve, I am not sure if you would call this a "heterogeneous container". I want to be able to pass different container types (which share common properties) to functions, and define conversions between the types if the function requires a specific type.
The way I've thought to do this thus far is to have an abstract parent class HetroContainer
, which specific types inherit from. The concrete type can be fetched by an enum defined in HetroContainer
, where each enum element is a convenient label for the type of the child container.
Say I have two functions:
HetroContainer my_fun_a(HetroContainer input) {...}
HetroContainer my_fun_b(HetroContainer input) {...}
Both take and return HetroContainer
. However, internally my_fun_a
deals with let's say std::vector
s, enum id VEC1
, and my_fun_b
deals with some other type, say Eigen tensors, or an std::vector
but with a different element ordering, or whatnot, enum id VEC2
.
In pseudocode:
my_fun_X
- Take generic container input
- Check to see if the input container's data is of my_fun_X's preferred type
- If it is not, then convert to that type (can/should be to new object)
- Run computations on container's data
- Return container
The parent class might look something like, where one would need to downcast to access the data:
enum TypeEnum{VECTOR_FMT1,
VECTOR_FMT2,
EIGEN};
class HetroContainer
{
public:
HetroContainer(TypeEnum the_type,
int param1, int param2)
:
_the_type(the_type),
_param1(param1), _param2(param2)
{};
TypeEnum the_type() const { return this->_the_type;};
int param1() const { return this->_param1; };
int param2() const { return this->_param2; };
virtual void convert(HetroContainer input) = 0;
private:
std::any _data;
TypeEnum _the_type;
int _param1;
int _param2;
};
My program will deal with compositions of my_fun_a
and my_fun_b
, (and other my_fun_X
s). So if we have a composition my_fun_a(my_fun_a(input))
, then in the first step of the first my_fun_a
is to check if our HetroContainer
is of the needed type VEC1
.
The first my_fun_a()
runs, and returns a HetroContainer
, which is really a VEC1Container
. Our second my_fun_a
takes the HetroContainer
, and checks that its underlying type is VEC1
, so we don't need to bother converting.
In another case, my_fun_a(my_fun_b(input))
, my_fun_a
checks to see what the underlying type of its input is. It will find that it is not its required format (because my_fun_b()
deals with the type VEC2
. Thus, my_fun_a()
must first call the relevant convert function (VEC2 -> VEC1
) to convert the input to its required format. Once this conversion has finished, it continues running.
This conversion step will not necessarily be a simple cast, and will require manual implementation for each type-to-type. I would hope to be able to compose conversion, so that if I have a mapping from A->B
and B->C
, my program can infer that A->B->C
can be performed. For these functions, I have been looking at.
I have been looking at QA forums about the web, but have been running into problems with downcasting. It feels like the overall design could be approached better, but I am not sure what I should be looking for. Any suggestions would be appreciated!
Have looked at: