vendredi 16 juillet 2021

C++ Design Problem Regarding Templating, Containers and Inheritance

I have a problem with my design regarding interfacing algorithmic classes I have written and a third-party API. I will write some pseudocode to help explain my problem. I would prefer not to involve boost if possible.

The Problem

I have an algorithm class I will call Alg (it can be thought of as a search/optimisation algorithm) and a "super" algorithm class I will call SuperAlg which holds a number of Alg objects in a std::vector<Alg>. The SuperAlg evaluation function relies on a third-party algorithm, and thus needs to convert the result of any number of these Alg class objects into a third-party type. Each Alg may be associated with a different third-party type, which is known at the construction-time of the Alg class objects. The SuperAlg evaluation function looks something like:

double SuperAlg::evaluate(const std::vector<AlgResultType>& input) {
    ThirdPartyValues values;
    for (const auto& i : input) {
        values.insert(convert(i));
    }
    ThirdPartyAlg alg;
    return alg.error(values);
}

Here:

  • the ThirdPartyValues::insert is a templated function in the third-party API that knows how to take many different third-party types
  • ThirdPartyAlg::error takes a ThirdPartyValues and returns a double.
  • input is a vector of all the results from the Alg searches, with a 1-to-1 correspondence with the std::vector<Alg> owned by the SuperAlg class.

There are a lot of these third-party types and let's say that if I know the type and have the result of an Alg search (AlgResultType), I know how to perform the conversion. i.e. The convert function is known:

ThirdPartyType convert<ThirdPartyType>(const AlgResultType& result);

The fundamental problem is this: How can I specify the type of i I need to convert to in SuperAlg::evaluate? Recall that this type is known at the construction time of each Alg and somehow needs to be retained.

Some Solution Thoughts

  • If Alg/AlgResultType are templated with ThirdPartyType and the convert<ThirdPartyType> function is exposed through their interface, then they cannot be held in a dynamic-sized homogeneous containers and c++ doesn't have a dynamic-sized heterogenous container type.
  • Often the way around holding many different types (e.g. due to their template), Alg<ThirdPartyType>/AlgResultType<ThirdPartyType> in this case, is to have a common base class and have std::vector hold this base class, however this base class would need to have the convert<ThirdPartyType> function in order to be useful in SuperAlg::evaluate, which relies on the template parameter.
  • Some sort of container of types whereby each Alg or AlgResultType could be associated with a ThirdPartyType, but I know of no such container.

Aucun commentaire:

Enregistrer un commentaire