I'm working on some library code, and I want users to be able to take advantage of static binding if they are able to. If they are unable to instantiate a class at compile time, I want there to be a dynamic version of the class, so that it can be instantiated at run-time.
For a quick example, say I have a structure template A:
template<bool dynamic, int value=0> struct A
{
static const int Value = value;
};
template<> struct A<true>
{
int Value;
A(int value) : Value(value) {}
};
These definitions allows users of the library to instantiate A statically, and dynamically:
A<true> dynamicA = A<true>(5);
A<false, 5> staticA;
The problem with this method is that I have to write the definition of the class twice. I can think of a few ways of implementing a template that would generate both versions myself, but I can see it becoming a lot of work. Especially for classes that would use varying numbers of parameters, for example:
// It would be much harder to generate a static version of this class,
// though it is possible with type lists. Also, the way I'm imagining it,
// the resulting classes probably wouldn't be very easy to use.
struct A
{
vector<int> Values;
A(vector<int> value) : Values(value) {}
};
Is there a name for this pattern / problem? Is there a meta programming library which has templates which can generate both definitions for me? How do I avoid having to write the definitions of my classes twice?
There is a simple mechanism to get the parts that do not depend on the dynamic/static value problem into one single location: put them into another class, let's call it
basic_A
, and let's call the static/dynamic value container you show in the questionvalue_A
. There are different ways to connectvalue_A
andbasic_A
to form the completeA
class:Aggregation of
basic_A
insidevalue_A
. This would mean you have to route every method ofbasic_A
throughvalue_A
and provide the corresponding one-liners in both specializations ofvalue_A
. This is probably not much of a gain because you have to duplicate all of the one-liners, so scratch that.Aggregation of
value_A
insidebasic_A
. You would either have to makebasic_A
a template too, only to pass the parameters to thevalue_A
and provide the correct constructors for both specializations, probably somehow disabling and enabling them via SFINAE. Not a very beautiful and maintainable piece of code, either. The alternative would be to make a common base class (Interface) for the two specializations ofvalue_A
, have aunique_ptr
to that interface inbasic_A
and pass the ready constructedvalue_A
intobasic_A
's constructor, at the cost of a virtual function call and poitner indirection whenever you want to access the value. Yuck, especially ifA
is meant to be a small and fast lightweight class.Inherit
basic_A
fromvalue_A
. The same problems as in 2. apply, regarding constructors and forwarding of template parameters.Inherit
value_A
frombasic_A
. The construction problem disappears, but nowbasic_A
can not easily accessvalue_A
's value. One solution would be to have a pure virtual functiongetValue()
inbasic_A
which the two specializations ofvalue_A
have to implement. This again has the cost of a virtual function dispatch which might not be desirable for a small lightweight class, but it enables encapsulation, sincebasic_A
is a non-template and can hide its implementation in a .cpp file. The other approach would be to use compiletime polymorphism vía the CRTP, which would makebasic_A
a template again.Here are two examples for the two approaches of 4.:
4a:
getValue()
as a virtual function:4b:
getValue()
vía CRTPThe template
A
aka.A_value
for 4b follows. For 4a it is alsmost the same, just lose the template arguments and brackets frombasic_A
since it is a plain class: