I want to implement a factory function for creating objects. My object template looks like this:
template <typename TA, typename TB>
struct MyImpl : public MyInterface
{
// content
};
and my factory is like this:
MyInterface* factory(char ta, char tb)
{
if(ta == 'c' && tb == 'c')
{
return new MyImpl<char, char>();
}
if(ta == 'c' && tb == 's')
{
return new MyImpl<char, short>();
}
if(ta == 's' && tb == 'c')
{
return new MyImpl<short, char>();
}
// and so on ....
}
The factory function must accept non-static char data (ta
, tb
) for it could not be determined at compile time, and I think that's the whole point of this factory. In fact, ta
and tb
are read from a file (or network).
I want a simpler solution to avoid the annoying 2-level switch.
I think my question is similar to how-would-one-write-a-meta-if-else-if-in-c with the exception that I cannot use static parameters.
Perhaps I should just fallback to C macros and use some macro tricks to shrink my current code?
Thanks in advance!
UPDATE
Answer to @Rob:
My actual code would be more complex with many other stuffs in it and harder to read and not related in many aspects. I'm trying to get the pseudo-code right, If there is any problem, please kindly inform me :-).
Answer to @Dynguss:
My problem is that in my actual implementation, parameters of the factory (ta, tb) would be large in range, like 10 X ta and 20 X tb, and combination of ta and tb would be very long in lines, and hard to maintain. So I need at least some way to ease the combination efforts.
Here's an idea:
template <typename T>
MyInterface * factroy(char t)
{
if (t == 'c') { return MyImpl<T, char>(); }
if (t == 's') { return MyImpl<T, short>(); }
// ...
}
MyInterface * factory(char ta, char tb)
{
if (ta == 'c') { return factroy<char>(tb); }
if (ta == 's') { return factroy<short>(tb); }
// ...
}
With variadic templates, this pattern could be extended to any number of type arguments – for example:
struct Base { virtual ~Base() = default; };
template <typename A, typename B, typename C> struct Foo : Base { };
#include <tuple>
template <typename ...Args>
constexpr Base * factory(std::tuple<Args...>)
{
return new Foo<Args...>;
}
template <typename ...Args, typename ...Char>
constexpr Base * factory(std::tuple<Args...>, char t, Char ... ts)
{
return t == 'c' ? make(std::tuple<char, Args...>(), ts...)
: t == 's' ? make(std::tuple<short int, Args...>(), ts...)
: t == 'i' ? make(std::tuple<int, Args...>(), ts...)
: t == 'l' ? make(std::tuple<long int, Args...>(), ts...)
: nullptr;
}
Usage: auto p = factory(std::tuple<>(), 'c', 's', 'l');
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