vendredi 9 octobre 2015

Typesafe method for retrieving data of unknown type through interface

TL;DR version:

I am designing a class in C++14 to be generic. Below I describe a design problem, and I would be grateful for a solution to implement what I'm trying, or a suggestion for a redesign.

Say the class I'm designing is called Algo. Its constructor is passed a unique_ptr to a type, say Business, which implements an interface (i.e., inherits from a pure virtual class) and does most of the serious work.

I want an object of type Algo to be able to return a pointer (or even a copy) of a data member from the Business object that it owns. But it can't know the type that Business will want to return. I expect the owner of Algo to know what will come out based on what Business he passed in.

In my C days, I would blow off the type system by passing around void* and casting as needed. But that sort of thing now wreaks to me.

More detail:

So, a sort of pseudo-C++14 implementation of the above situation might look like:

// perhaps a template here?
class AbstractBusiness {
  ?unknownType? result();
};

class Algo {
  unique_ptr<AbstractBusiness> concreteBusiness_;

 public:
  Algo(std::unique_ptr<AbstractBusiness> concreteBusiness);
  auto result() {return concreteBusiness_.result();}
};

class Business : public AbstractBusiness {
  std::valarray<float> data_;
  . . .
 public:
  std::valarray<float> result() {
    return data_;
  }
};

:::

auto b = std::unique_ptr<AbstractBusiness>{std::move(new Business())};
Algo a(std::move(b));
auto myResult = a.result();

In this example, myResult will be a std::valarray<float>, but I don't want Algo or the AbstractBusiness interface to have to know that! The creator of b and a should be in charge of knowing what should come out of a.result().

If I am taking a wrong turn in this design, don't hesitate to let me know. I'm a bit green at this point and very open to suggestions.

I've tried... I obviously can't use auto for a virtual method, nor have a template in a virtual class. These are the only things that stood out.

I'm playing with the idea of making a container interface for whatever Business.result() returns, and just passing pointers to abstract type up to Algo.result(). But I'm starting to feel like there may be a better way, so I'm on here begging for suggestions.

Aucun commentaire:

Enregistrer un commentaire