I have the following situation:
Given this class:
template<typena me T>
class Expression {
/* omitted */
};
This is the base class for a BooleanExpressi on and an ArithmeticExpre ssion.
Now I have another struct, that contains a BooleanExpressi on and an
ArithmeticExpre ssion. This expression will be either Expression<int> or
Expression<stri ng>. Which one is determined at runtime. The problem I'm
faced with is how to store them. Basically, I'm leaning toward two different
options.
1. Create a base class BaseExpression, that doesn't really do anything at
all, and have Expression inherit from it, making the other class like this:
struct MatchModifier
{
BaseExpression *test;
BaseExpression *operation;
};
I'll have a flag somewhere that I'll need to have anyway that'll tell me the
type it's going to be, so I could then dynamic_cast them whenever I need to
use them.
2. Just have two pointers, only one of which is used:
struct MatchModifier
{
BooleanExpressi on<int> *intTest;
BooleanExpressi on<std::string> *stringTest;
ArithmeticExpre ssion *intOperation;
std::string *stringOperatio n;
};
As you can see here, there's not actually an
ArithmeticExpre ssion<std::stri ng>, it'll just be a plain string.
From my perspective, option two holds the best cards. It clearly relates the
fact that test is always a BooleanExpressi on and that operation is always an
ArithmeticExpre ssion (or string constant). It also means I don't need to
create an additional class that has no real purpose, and I won't need to
create a StringConstant class or whatever that inherits from BaseExpression
to wrap the std::string. It's also more performant (I think) as the
expressions will be used often, and for option 1 that means a dynamic_cast
every single time, and option 2 just involves picking one of two pointers.
Option 2 does waste 8 bytes per MatchModifier, but that's not such a big
problem, and I could always use unions if that really becomes a concern.
Option 2 does have the distinct disadvantage that adding additional
Expression types adds more work, but at this time it doesn't seem likely
that that'll happen.
However, somehow my sense of style has a little voice in my head saying that
option 2 is wrong somehow, that there must be a more elegant solution. But
all I can come up with is solution 1.
So, which would you prefer. Or would you perhaps know a better, third
alternative?
Thanks in advance for any input.
--
Unforgiven