0

For a policy-based class-design I need some of the policies to call functions that are found in other policies:

struct PolicyA {
  void foo() {
    // ...
  }
};

struct PolicyB {
  void bar() {
    // Need to call foo() here
  }
};

template <class A, class B> MyClass : A, B {};

The two options I see are:

  • Pass MyClass<A, B> to PolicyA and PolicyB as template parameters and do something like dynamic_cast<MyClass<A, B>*>(this)->foo();. However this may easily get very complicated (especially if it's not only B calling A but also the other way).
  • Have a base class for each policy where all the functions are declared as pure virtual. This fails when one of the function needs its own template parameters, since virtual template functions are not possible.

This should be a common problem, but I didn't find anything. I guess there probably is some boost-magic or something. How would you solve this?

Edit: See also the followup here.

Community
  • 1
  • 1
lucas clemente
  • 6,255
  • 8
  • 41
  • 61

1 Answers1

1

Why doesn't PolicyB encapsulate PolicyA and call it as it needs? PolicyB is obviously aware of PolicyA - no need for base classes or inheritance.

It seems like all of your Policy implementations have some common apply method that outside callers can agree upon?

Edit:

Right, so if it's not just a simple case of one particular Policy implementation needing access to another, you should probably focus on creating a single interface for Policy - perhaps even a Rule class that can be composed together to form a particular Policy - see the Specification pattern.

class Rule {
    allows(Foo foo);
}

class Policy {
    Rule rule = new NotNullRule().and(someOtherRule);

    void applyTo(Foo foo) {
        if (rule.allows(foo)) {
            return foo;
        }
        foo.disable();
    }
}

Call them whatever you want, Condition, Rule, Specification - they're useful for assembling pieces of logic together in a manner that doesn't depend on them. Then when someone is looking at PolicyA they can see, clearly, the rules/conditions that govern its behavior, objectified.

Once you have policy implementations in place, if you need to enforce several policies on something, you can use the composite pattern again so that external classes only see a Policy interface. But again, you have a clear 'named' policies that are being referred to, not just cross-calling functions.

Doug Moscrop
  • 4,479
  • 3
  • 26
  • 46
  • Encapsulating doesn't work if I want both policies to be able to call each other. But as KerrekSB noted in the comments, maybe this ist just bad design. I'll think about it… – lucas clemente Nov 30 '11 at 13:42
  • @lucasclemente: If you like, you can post some details of what you're trying to do. Maybe a minimal, representative example. Then we can think of alternative solutions. – Kerrek SB Nov 30 '11 at 13:58
  • Hm, I thought about it and figured out some way to design it in a nicer way. Thanks! – lucas clemente Nov 30 '11 at 18:17
  • @KerrekSB: Didn't quite work out the way I thought it would. I've posted a followup here: http://stackoverflow.com/q/8334926/220918 – lucas clemente Dec 01 '11 at 00:11