Помогите днищу. Не могу придумать как сделать такую иерархию.
Есть набор операций, пусть будет add/sub/mul/div. Есть общий класс, который реализует представление и реализацию этих операций. И есть конкретные классы самих операций, которые реализуют и хранят уникальные данные/методы.
Как это реализовать.
namespace op {
  class op_base {//т.е. это общий класс для операций
  public:
    op_base(int a, int b) : a(a), b(b) {}
    int op();//т.е. это конкретная операция, которая как-то должна экспортироваться из каждой конкретной операции;
    operator int() {return op();}
  protected:
    int a, b;
  };
  
  class op_add {//это конкретная операция.
    int op() {return a + b};//конкретная операция
  };
  
  class op_mul {//это конкретная операция.
    int op() {return a * b};//конкретная операция
  };
  
  //в конечном итоге нам надо получить объект op_base, в котором op() бы заменялась на конкретную реализацию.
  //т.е. и 
  add(1, 2);
  //и
  mul(1, 2);
  //были объектами op_base, но в чём-то были уникальны.
};
Я уже не могу - помогите. Эти перекрёстные ссылки меня доконают.
//попытка запилить на вариенте не удалась так же, как и сотни других.
namespace variant_hell {
  struct op_add; struct op_mul;
  using op_var =  boost::variant<op_add *, op_mul *>;
  class op_visitor : public boost::static_visitor<int> {
  public:
    int operator()(op_add * op) const {return op->op();}
    int operator()(op_mul * op) const {return op->op();}
  };
  class operation {
  public:
    operation() {}
    template<typename op> operation(int a, int b, boost::mpl::identity<op>) : a(a), b(b), cop { new op{*this}} {}
    operator int() {
      return boost::apply_visitor(op_visitor(), cop);
    }
  public:
    int a, b;
  private:
    op_var cop;
  };
  struct op_add {
    op_add(operation & base) : base(base) {}
    int op() {return base.a + base.b;}
    operation & base;
  };
  struct op_mul {
    op_mul(operation & base) : base(base) {}
    int op() {return base.a * base.b;}
    operation & base;
  };
  template<typename T> struct wrapper {
    wrapper(int a, int b) : op(a, b, boost::mpl::identity<T>()) {}
    operator operation() {return op;}
    operation op;
  };
  
  auto add(int a, int b) {return wrapper<op_add>(a, b);}
}
Операции должны быть именно полноценными, отдельными классами. Класс «операция» должен быть один на всех. Класс операция - основной, который должен иметь в себе доступ к сабклассам, которые «операции».
Отдельные операций тысячи. Поэтому никакая «шаблонная база» не подходит.
Вариант с вариантом хорошо ложится на логику, но я так и не смог.
Нагинерить тонны лапши не проблема.
Может я делаю что-то не так и это делается проще?

