Motivation: (Skip to "The Problem" if you don't need motivation for it)
As a project for myself, I'm writing an expression parser for certain kinds of mathematical expressions, and I'm using the interpreter pattern (as it often is used) for my Expression classes.
At the same time, I'm also using the template method pattern for certain operations I wanna do on my Expressions. My use of the template method pattern is where the template method is "public", but the primitive operations called by the template method should not be "public" to the user. (This is how I learnt it, and this feels like it makes the most sense for my program.)
The specific example I was dealing with was trying to simplify an expression; there are several different simplification functions (let us call them simplify1, simplify2, and so on) I used, and each are called inside the Expression class (for example, one of my simplification functions evaluates all constant expressions, e.g. 1+2^(2*3) simplifies to 65, another simplification function simplifies repeated operations, eg. x+(3+x^2) simplifies to x+3+x^2). The way this works in each of the Expression subclasses which are non-terminal is that there are recursive calls to the contained expressions, until a terminal "Constant" or "Variable" is reached.
Now, the problem is that these different simplification functions should be hidden from the user; the interface should only allow a call to the template method "simplify", which calls all the different simplification functions as needed. Initially, I thought that making those simplify functions "protected" would solve the problem. That is, in my child classes, I would have "simplify1", "simplify2" and so on overridden, and then in the parent expression class, "simplify" would call "simplify1", then "simplify2", and so on, and "simplify" itself would be public. However, the problem is that in non-terminal classes (an expression that itself contains expressions), having a protected modifier on simplify1, simplify2, and so on, does not allow it to call simplify1, simplify2, etc. on the contained expressions.
The Problem:
Abstracting away the motivation ("Expression" becomes "Parent", the different derived expression classes are the "Child" classes ("ChildC" specifically is a non-terminal expression), "simplify" becomes "publicFoo", and "simplify1" and "simplify2" become "foo1" and "foo2" respectively), I want code that behaves like this:
class Parent { //abstract expression
protected:
virtual void foo1() = 0; //primitive operation, don't wanna give access to public
virtual void foo2() = 0; //primitive operation, don't wanna give access to public
public:
void publicFoo(){ //template method
this -> foo1();
this -> foo2();
//maybe does other things too
}; // this is what the user will call
};
class ChildA: public Parent { //terminal expression
protected:
void foo1() override; //whatever implementation
void foo2() override; //whatever implementation
};
class ChildB: public Parent{ //terminal expression
protected:
void foo1() override; //whatever implementation
void foo2() override; //whatever implementation
};
class ChildC: public Parent { //non terminal expression
std::vector<Parent*> parents;
protected:
void foo1() override {
for ( auto p: parents){
p->foo1(); //calls correct foo1 depending on what p truly is (this does not compile)
}
}
void foo2() override {
for ( auto p: parents){
p->foo2(); //calls correct foo2 depending on what p truly is (this does not compile)
}
}
};
So, the problem here is that "protected" actually doesn't allow calling foo1 or foo2 on arbitrary Parent type objects, only on ChildC objects, and the compiler gives me errors saying "'foo1' is a protected member of 'Parent'" and "'foo2' is a protected member of 'Parent'". It feels like what I want is a modifier that's something like "semi-protected", which allows access for a derived class to call semi-protected functions of any kind of parent object.
Temporary Solution:
My current solution to this is to simply make the ChildC (in the example above) a friend class to Parent, and then make foo1 and foo2 private (because ChildC, as a friend, can access those anyway). However, in my time using C++, I've learnt that friend classes are usually discouraged and are considered bad style (or something of the sort). And in general, the solution doesn't feel as nice as it could be, because I don't need ChildC to have that much access to Parent's members.
Question:
Thus, my question is, is there a nicer way to combine these patterns while ensuring that the primitive operations with the template method pattern remain hidden to the user?