#include <functional>
#include <iostream>
#include <vector>
 
enum System { SYS_A, SYS_B, SYS_C };
 
class Command {
public:
  typedef std::function<void()> FuncType;
 
  Command(FuncType func, std::initializer_list<System> requirements)
  :func_(func), requirements_(requirements) { }
 
  void operator()() {
    std::cout << "Executing Command:" << std::endl;
    for ( System s : requirements_ )
      std::cout << "   REQUIRES " << static_cast<int>(s) << std::endl;
    func_();
  }
 
private:
  FuncType            func_;
  std::vector<System> requirements_;
};
 
class Scheduler {
public:
  void add(Command c) {
    c();
  }
};
 
class Robot {
public:
  Robot()
  :do_something_    (std::bind(&Robot::do_something, this),     {SYS_A, SYS_B}),
   do_another_thing_(std::bind(&Robot::do_another_thing, this), {SYS_A, SYS_C}) { }
 
  void runRobot() {
    s_.add(do_something_);
    s_.add(do_another_thing_);
  }
 
private:
  void do_first_thing()  { std::cout << "   FIRST THING!" << std::endl;  }
  void do_second_thing() { std::cout << "   SECOND THING!" << std::endl; }
  void do_third_thing()  { std::cout << "   THIRD THING!" << std::endl;  }
 
  void do_something()     { do_first_thing(); do_second_thing(); }
  void do_another_thing() { do_first_thing(); do_third_thing();  }
 
  Command   do_something_;
  Command   do_another_thing_;
  Scheduler s_;
};
 
int main(int, char**) {
  Robot().runRobot();
}
				I2luY2x1ZGUgPGZ1bmN0aW9uYWw+CiNpbmNsdWRlIDxpb3N0cmVhbT4KI2luY2x1ZGUgPHZlY3Rvcj4KCmVudW0gU3lzdGVtIHsgU1lTX0EsIFNZU19CLCBTWVNfQyB9OwoKY2xhc3MgQ29tbWFuZCB7CnB1YmxpYzoKICB0eXBlZGVmIHN0ZDo6ZnVuY3Rpb248dm9pZCgpPiBGdW5jVHlwZTsKCiAgQ29tbWFuZChGdW5jVHlwZSBmdW5jLCBzdGQ6OmluaXRpYWxpemVyX2xpc3Q8U3lzdGVtPiByZXF1aXJlbWVudHMpCiAgOmZ1bmNfKGZ1bmMpLCByZXF1aXJlbWVudHNfKHJlcXVpcmVtZW50cykgeyB9CgogIHZvaWQgb3BlcmF0b3IoKSgpIHsKICAgIHN0ZDo6Y291dCA8PCAiRXhlY3V0aW5nIENvbW1hbmQ6IiA8PCBzdGQ6OmVuZGw7CiAgICBmb3IgKCBTeXN0ZW0gcyA6IHJlcXVpcmVtZW50c18gKQogICAgICBzdGQ6OmNvdXQgPDwgIiAgIFJFUVVJUkVTICIgPDwgc3RhdGljX2Nhc3Q8aW50PihzKSA8PCBzdGQ6OmVuZGw7CiAgICBmdW5jXygpOwogIH0KCnByaXZhdGU6CiAgRnVuY1R5cGUgICAgICAgICAgICBmdW5jXzsKICBzdGQ6OnZlY3RvcjxTeXN0ZW0+IHJlcXVpcmVtZW50c187Cn07CgpjbGFzcyBTY2hlZHVsZXIgewpwdWJsaWM6CiAgdm9pZCBhZGQoQ29tbWFuZCBjKSB7CiAgICBjKCk7CiAgfQp9OwoKY2xhc3MgUm9ib3QgewpwdWJsaWM6CiAgUm9ib3QoKQogIDpkb19zb21ldGhpbmdfICAgIChzdGQ6OmJpbmQoJlJvYm90Ojpkb19zb21ldGhpbmcsIHRoaXMpLCAgICAge1NZU19BLCBTWVNfQn0pLAogICBkb19hbm90aGVyX3RoaW5nXyhzdGQ6OmJpbmQoJlJvYm90Ojpkb19hbm90aGVyX3RoaW5nLCB0aGlzKSwge1NZU19BLCBTWVNfQ30pIHsgfQoKICB2b2lkIHJ1blJvYm90KCkgewogICAgc18uYWRkKGRvX3NvbWV0aGluZ18pOwogICAgc18uYWRkKGRvX2Fub3RoZXJfdGhpbmdfKTsKICB9Cgpwcml2YXRlOgogIHZvaWQgZG9fZmlyc3RfdGhpbmcoKSAgeyBzdGQ6OmNvdXQgPDwgIiAgIEZJUlNUIFRISU5HISIgPDwgc3RkOjplbmRsOyAgfQogIHZvaWQgZG9fc2Vjb25kX3RoaW5nKCkgeyBzdGQ6OmNvdXQgPDwgIiAgIFNFQ09ORCBUSElORyEiIDw8IHN0ZDo6ZW5kbDsgfQogIHZvaWQgZG9fdGhpcmRfdGhpbmcoKSAgeyBzdGQ6OmNvdXQgPDwgIiAgIFRISVJEIFRISU5HISIgPDwgc3RkOjplbmRsOyAgfQoKICB2b2lkIGRvX3NvbWV0aGluZygpICAgICB7IGRvX2ZpcnN0X3RoaW5nKCk7IGRvX3NlY29uZF90aGluZygpOyB9CiAgdm9pZCBkb19hbm90aGVyX3RoaW5nKCkgeyBkb19maXJzdF90aGluZygpOyBkb190aGlyZF90aGluZygpOyAgfQoKICBDb21tYW5kICAgZG9fc29tZXRoaW5nXzsKICBDb21tYW5kICAgZG9fYW5vdGhlcl90aGluZ187CiAgU2NoZWR1bGVyIHNfOwp9OwoKaW50IG1haW4oaW50LCBjaGFyKiopIHsKICBSb2JvdCgpLnJ1blJvYm90KCk7Cn0=