I want to create something like an universal factory method - look at this one:
template <class BaseType>
class Factory {
public:
template <class ... Args>
static BaseType* Create(const Args& ... args) {
return new DerivedType(args ...);
}
};
Where the DerivedType
is some other type derived from BaseType
and defined in a different place.
The problem is with storing DerivedType
. I want to do it, for example, like this:
void f() {
// Derived type may have more than one constructor,
// that's why I suggest using of the variadic templates.
BaseType* ptr1 = Factory<BaseType>::Create("abc", 5, 10.);
BaseType* ptr2 = Factory<BaseType>::Create();
...
}
...
Factory<BaseType>::SetType<MyDerivedType>();
f();
Factory<BaseType>::SetType<YourDerivedType>();
f();
I can set different derived types, but all of them are known at compile-time. I can't think of an appropriate technique to do this.
Question: Can you advise one?
The rationale of doing this (thus, the original problem, if someone suggests the question is it-self the XY problem) - is an ability to unit-test some tricky parts of code. For example, if I have a code:
...
Shuttle* shuttle1 = new ShuttleImpl("Discovery", Destination::Moon);
Shuttle* shuttle2 = new ShuttleImpl();
...
And I don't want to really construct the shuttle each time I run unit-tests:
class Shuttle: public Factory<Shuttle> { ... }
...
Shuttle* shuttle1 = Shuttle::Create("Discovery", Destination::Moon);
Shuttle* shuttle2 = Shuttle::Create();
...
So, in the unit-test I can just do: Shuttle::SetType<TestShuttle>();
.
There may be more "testable" classes, that's why I need an universal factory for all of them:
class Car: public Factory<Car> { ... }
class Driver: public Factory<Driver> { ... }
...
Not a complete answer, but your class template's Create
static function template should be:
template <class BaseType>
class Factory {
public:
template <class... Args>
static BaseType* Create(Args&&... args) {
return new DerivedType(std::forward<Args>(args)...);
}
};
See also When to use std::forward to forward arguments?
Edit:
Why does a second template argument not solve your problem?
For example:
template <class Base, class Derived>
class Factory {
public:
template <class... Args>
static Base* Create(Args&&... args) {
return new Derived(std::forward<Args>(args)...);
}
};
Instead of
Factory<BaseType>::SetType<MyDerivedType>();
f();
Factory<BaseType>::SetType<YourDerivedType>();
f();
you may write:
Factory<MyBase, MyDerived1> factory1;
Factory<MyBase, MyDerived2> factory2;
auto object1 = factory1::Create(1, "a");
auto object2 = factory2::Create(1.2, "abc");
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With