I have a hierarchy of class templates. At the top of the hierarchy is an abstract base class (interface). I won't know which concrete implementation to instantiate until runtime, so it seems like the perfect situation to use the factory pattern. However, virtual member function templates are not allowed in C++.
How can I achieve a legal design similar to the below in C++?
The individual concrete implementations of the IProduct interface as well as the concrete factories will live in different dynamic libraries, one or more of which will be loaded at runtime.
template<class T> class IProduct
{
public:
virtual void doWork(const T & data) = 0;
};
template<class T> class ProductA : public IProduct<T> {/*...*/};
template<class T> class ProductB : public IProduct<T> {/*...*/};
class IProductFactory
{
public:
template<class T> virtual IProduct<T> * createProduct() = 0;
};
class ProductAFactory: public IProductFactory
{
public:
template<class T> virtual IProduct<T> * createProduct()
{
return new ProductA<T>;
}
};
class ProductBFactory: public IProductFactory
{
public:
template<class T> virtual IProduct<T> * createProduct()
{
return new ProductB<T>;
}
};
Why can't you templatize IProductFactory on T as well? That would get rid of your error, and it's no less general. The client is still going to have to know what T is in order to call thecreateProduct method.
Edit Re: comment
In order to do this, you will need to just create a templatized function to create the factory. So:
template<class T> IProductFactory<T>* getProductFactory();
Now your factory is templatized, the createProduct method is no longer a member template. Not sure what your criteria is for returning a ProductAFactory vs. a ProductBFactory but you will either have to pass in a string to choose, have this be a member function of another class that would make the decision, or have multiple free functions but only expose one version or another to a particular client.
This doesn't need a template. Does that eliminate your problem?
Related
I want to implement the visitor pattern for one of my class without having to depend on the types that will implement the interface to visit them.
My solution was this:
class model::VisitableNode {
public:
template<class T>
virtual T accept(NodeVisitor<T>);
}
But C++ says that it doesn't support template + virtual methods
Node in my application will have only one implementation but if I don't use a template return type my model class will depend on the toolkit that I'm using to create the graphic for my app.
If a visitor needs to return a value, it is normal to store the returned value in the visitor itself. Thus:
NodeVisitor<double> dv;
node->accept(dv);
double result = dv.result();
If you don't like the boilerplate, you can wrap it in a non-virtual member:
class model::VisitableNode {
public:
template<class T>
/* non-virtual */ T accept(NodeVisitor<T>& v) {
do_accept(v);
return v.result;
}
virtual void do_accept(NodeVisitorBase& v) = 0;
}
Why not template the class itself?
template<class T>
class model::VisitableNode<T> {
public:
virtual T accept(NodeVisitor<T>);
}
I'm a bit new to templates so bear with me if I'm asking obvious questions.
Given the following class hierarchy:
template<typename T>
class Singleton_T
{
...
static T& getInstance(){ ... }
...
}
template<typename T>
class Pool_T: public Singleton_T<Pool_T<T> >
{
...
T* createObject();
...
}
Now I want a class that extends the Pool_T functionality while also being a Singleton_T.
So I want to have in the new class the methodsgetInstance defined in Singleton_T and createObject defined in Pool_T tailored to my new type.
The initial approach would be:
struct myStruct;
class Manager : public Pool_T<myStruct>
{
...
void loadObjectsFromFile();
...
}
However , this makes the GetInstance of the Singleton_T to instantiate and return Pool_T<myStruct> type, so the loadObjectsFromFile method won't be available via getInstance (an object of Manager type won't be created).
In order to solve this I made the following change in hierarchy :
template< typename TDerrived, typename T>
class Pool_T : public Singleton_T < TDerrived >
{
...
T* createObject();
...
}
class Manager : public Pool_T<Manager, myStruct>
{
...
loadObjectsFromFile();
...
}
Now I can use all the three methods: getInstance, createObject and loadObjectsFromFile.
However this forces Pool_T to no longer be possible to instantiate from only 1 type.
EG:
struct someStruct;
class StructPool : public Pool_T<someStruct>; // no longer possible
In order to "solve" this i defined another template:
template <typename T>
class AlonePool_T: public Pool_T<AlonePool_T<T>, T>
{
// empty class
// allows instantiation of what was previously Pool_T<someStruct>
}
Now I can use this where previously Pool_T<someStruct> was defined.
struct someStruct;
class StructPool : public AlonePool_T<someStruct>;
However this will result in allot of find and replace in code that I'm not owner off.
Is there any way to achieve the following:
maintain Pool_T original definition
create a class that extends the Pool_T functionality (adds the loadObjectsFromFile method)
the class has getInstance and createObject methods correctly implemented (the correct types are used)
EDIT:
Added three methods to better underline the desired effect.
Given's liliscent's answer I changed the hierarchy to better show what I'm after.
If I understand your question correctly, a typical CRTP implementation of your hierarchy is:
template<class T>
struct Singleton {};
template<class Derived, class T>
struct Pool
: public Singleton<Derived>
{};
struct MyStruct {};
struct Manager
: public Pool<Manager, MyStruct>
{};
I need advice on how to design an interface, the problem is simplified like this:
I have to design a set of checking classes for some classes, at first there is only one class to be checked, now I need to do checking for a new class which requires a new interface, something like this:
In the beginning,
Class Base{ blah;};
Class D1 public Base {...};
Class IChecker { virtual bool CheckIt(Base*) = 0; };
Class Checker1 public IChecker;
Class Checker2 public IChecker;
......
Now I need to check on a new class:
Class D2 public Base {...};
To check this D2, I need a different interface
virtual bool CheckIt(const vector<unique_ptr<Base>> &) = 0;
My Question is, which is a better OO design,
Should I implement a aggregated IChecker
class IChecker{
virtual bool CheckIt(Base*) = 0;
virtual bool CheckIt(const Vector<unique_ptr<Base>>&) = 0;
}
class Checker1 public IChecker {};
class Checker2 public Ichecker {};
......
Or Should I make two ICheckers for each types to be checked:
class ICheckerD1 { virtual bool CheckIt(D1*) = 0; }
and
class IcheckerD2 { virtual bool CheckIt(vector<unique_ptr<D2>>&) = 0; }
This time the solid checkers will look like this:
class Checker1D1 public ICheckerD1 {};
class Checker2D1 public IcheckerD1 {};
class Checker1D2 public IcheckerD2 {};
Thanks a lot!
It would be better design and less code redundance if you implement a single IChecker class to work with several types in the case that you're working with set types only. However depending on your case it might be wise to use templated class.
Remember that unlike .Net or Java, C++ allows multiple inheritance from classes (not necessarily interfaces), so doing both would work fine.
An example of a templated class would be the following:
template <class T>
class IChecker {
public:
virtual bool CheckIt(const T& thingToCheck) = 0;
}
And you would inherit this way:
class InheritChecker : public IChecker<someClass>, public IChecker<someOtherType>
{
//Your method definitions here.
}
Summarizing it depends on your use case. If you will only use it for set types, then use only one class for all types. If you want the flexibility to be able to use any type any time. Make IChecker a templated class. That anyone can inherit from.
I am trying to define a templated base class that defines a virtual interface to be overriden by the user. In some cases it would make sense to have a default implementation of this method but that isn't true for all type parameters. Consider this:
template<typename T>
struct supplier
{
virtual std::unique_ptr<T> supply(std::istream& moreData) = 0;
};
Now I want to offer the following default implementation given that T is default constructible (std::is_default_constructible):
std::unique_ptr<T> supply(std::istream& moreData)
{
return std::unique_ptr<T>(new T);
}
The problem is not how to define this function for appropriate T but how to make it appear as a pure virtual function - and thus force an implementation by the user - when it's not defined and like a normal virtual function, if it is.
I think I'm just missing some obvious solution. I tried to specialize struct supplier but that means I'd have to define the rest of the interface two times, so it's definitly not a scaling solution. It also means that I have to provide the rest of the interface two times.
Is there an affordable solution for a rich base class with many virtual functions that may either offer an implementation or be purely virtual?
Extract the part you need to specialize into a separate class template, and then inherit from it.
namespace details {
template<class T, bool = std::is_default_constructible<T>::value>
struct supplier_base
{
virtual std::unique_ptr<T> supply(std::istream& moreData) = 0;
};
template<class T>
struct supplier_base<T, true>
{
virtual std::unique_ptr<T> supply(std::istream& moreData)
{
return std::unique_ptr<T>(new T);
}
};
}
template<class T>
struct supplier : details::supplier_base<T> { /* ... */ };
I have an interface IEnumerable for template classes of List<>, Array<> and Dictionary<>. I was hoping to use typedef to get their templated types T.
I was hoping to do the following.
class IEnumerable
{
public:
virtual typedef int TemplateType;
}
And then override in inherited member, but you cant make a virtual typedef. So is there any other way that i could get the type of an unknown template class (IEnumerable is not template)?
Well, here is what is discussed in the comments in case somebody with the same question later finds this.
Basically, you want to do something similar to C#'s List<>, Array<>, IEnumerable and IEnumerator. However, you don't want to have to create a generic parent class Object because it may mean that you'll need to dynamic_cast every time.
Additionally, you don't want to make IEnumerable a template because you don't want to have to know the type when using the collection.
In fact, with C++11, you can make IEnumerable a template and not have to know the type by using the implicit type keyword auto, which is the C++11 equivalent of c#'s var keyword.
So to do this, what you can do is:
template <class T>
class IEnumerable {
public:
virtual IEnumerator<T> getEnumerator() = 0;
// and more stuff
}
then
template <class T>
class List : public IEnumerable<T> {
public:
virtual IEnumerator<T> getEnumerator() {
return ListEnumerator<T>(this);
}
}
and
template <class T>
class ListEnumerator : public IEnumerator<T> {
public:
T getNext(); // or something to this effect
// and more stuff
}
Finally, when it comes to using it, you can do:
List<int> myList;
auto i = myList.getEnumerator();
int z = i.getNext()+1;