Not sure if this is even possible but here goes...
I'm trying to hide the param of a template base class by doing the following:
So far so good, but the problem is the return type of my factory class is IBase so the default implementation of foo is called instead of DerivedA or DerivedB :(
Anyway for this approach to work? or back to the drawing board?
// Common interface
class IBase {
public:
virtual std::string foo() { return "IBase"; };
}
// Template base class
template <typename T>
class Base : public IBase {
public:
Base(T value) : m_precious(value) {}
virtual ~Base() {}
protected:
T m_precious;
}
// Concrete derived classes
class DerivedA : public Base<int> {
public:
DerivedA(int value) : Base<int>(value) {}
virtual std::string foo() override {
return "DerivedA";
};
}
class DerivedB : public Base<float> {
public:
DerivedB(float value) : Base<float>(value) {}
virtual std::string foo() override {
return "DerivedB";
};
}
// Factory interface
class Factory {
public:
template<typename T>
static IBase create(T value);
};
template<>
IBase Factory::create<int>(int value) {
return DerivedA(value);
}
template<>
IBase Factory::create<float>(float value) {
return DerivedB(value);
}
// Caller
int main() {
int valueA = 3;
float valueB = 3.14;
// This is how I want to use the API
IBase A = Factory::create(valueA);
IBase B = Factory::create(valueB);
std::cout << A.foo() << std::endl;
std::cout << B.foo() << std::endl;
}
The above code prints:
IBase
IBase
But I want this:
DerivedA
DerivedB
You currently have object slicing, your code should be something like:
// Factory interface
class Factory {
public:
template<typename T>
static std::unique_ptr<IBase> create(T value);
};
template<>
std::unique_ptr<IBase> Factory::create<int>(int value) {
return std::make_unique<DerivedA>(value);
}
template<>
std::unique_ptr<IBase> Factory::create<float>(float value) {
return std::make_unique<DerivedB>(value);
}
With usage:
auto A = Factory::create(valueA);
auto B = Factory::create(valueB);
std::cout << A->foo() << std::endl;
std::cout << B->foo() << std::endl;