You can get it considerably more convenient by using Boost Fusion for the algorithmic part and Boost Phoenix for the bind part:
namespace phx = boost::phoenix;
namespace fus = boost::fusion;
template<typename... R>
class CompositeRule : public IRule
{
std::tuple<R...> m_rules;
public:
CompositeRule(R... rules) : m_rules(rules...) {}
virtual void Begin(int value) {
fus::for_each(m_rules, phx::bind(&IRule::Begin, arg1, value));
}
virtual double Evaluate(Context& context) {
return fus::accumulate(m_rules, 0.0, arg1 + phx::bind(&IRule::Evaluate, arg2, phx::ref(context)));
}
};
No more low-level template meta programming :/
For bonus, throw in a nice factory function:
template<typename... R>
CompositeRule<R...> make_composite(R&&... rules)
{
return CompositeRule<R...>(std::forward<R>(rules)...);
}
So you can have full type deduction:
int main()
{
auto combine(make_composite(RuleA(20), RuleA(), RuleA(100)));
DoSomething(&combine);
// you can even re-compose:
auto more(make_composite(combine, RuleA(-200), combine, combine, combine));
DoSomething(&more);
}
See it Live On Coliru
Check the output: (585.12 + 2 * 200) ÷ 246.28 == 4