Оператор копьё и сотоварищи
От: Arsenicum Россия  
Дата: 29.01.10 14:12
Оценка: 50 (19) :))) :))) :))) :))) :))) :))) :))) :))) :))
Впервые я увидел "оператор копьё" здесь (The "goes toward" operator). Он мне сразу приглянулся и мне захотелось придумать побольше таких операторов. В результате появился такой код:
// local
#include "warriors.hpp"

// stl
#include <iostream>

int main()
{
  Spearman s("Elmund", 15);
  Lancer l("Marius", 12);
  Hammerer h("Bork", 20);
  Macer m("Rigolus", 18);
  Merman mm("Novarro", 19);
  Thief t("Delon", 12);
  Gunner g("mr. Smith", 22);
  Bomber b("Akhmed", 19);

  std::cout << "-- The battle has been started --" << std::endl;

  s --> l;
  m --* h;
  h --()- s;
  l ----> g;
  mm ---E- m;
  t +- mm;
  g ,-- h;
  b ( )--* t;

  std::cout << "-- The battle has been finished --" << std::endl;

  return 0;
}

Вывод:
Elmund is entering the battle
Marius is entering the battle
Bork is entering the battle
Rigolus is entering the battle
Novarro is entering the battle
Delon is entering the battle
mr. Smith is entering the battle
Akhmed is entering the battle
-- The battle has been started --
Elmund is throwing spear to Marius
Marius has recieved 10 damage
Rigolus is beating Bork by mace
Bork has recieved 8 damage
Bork is crushing hammer on Elmund
Elmund has recieved 15 damage
Elmund is dead
Marius is piercing mr. Smith by lance
mr. Smith has recieved 20 damage
Novarro is striking Rigolus with trident
Rigolus has recieved 16 damage
Delon is backstabing Novarro by dagger
Novarro has recieved 16 damage
mr. Smith is shooting Bork from handgun at
Bork has recieved 30 damage
Bork is dead
Akhmed is blasting Delon
Delon has recieved 50 damage
Delon is dead
-- The battle has been finished --
Akhmed is leaving the battle with 19 health
mr. Smith is leaving the battle with 2 health
Delon's body is staying on the battleground
Novarro is leaving the battle with 3 health
Rigolus is leaving the battle with 2 health
Bork's body is staying on the battleground
Marius is leaving the battle with 2 health
Elmund's body is staying on the battleground

P.S. Компилировал на GCC-4.1.2, за другие компиляторы не ручаюсь.
P.P.S. Пользуясь случаем, прошу прощения за мой английский.
Re: Здесь вся магия
От: Arsenicum Россия  
Дата: 29.01.10 14:14
Оценка: 6 (2)
warriors.hpp
#pragma once

// local
#include "weapons.hpp"

// stl
#include <string>
#include <iostream>

class Warrior
{
public:

  Warrior(const std::string name, int health):
    m_name(name),
    m_health(health)
  {
    std::cout << m_name << " is entering the battle" << std::endl;
  }

  ~Warrior()
  {
    if (m_health > 0)
      std::cout << m_name << " is leaving the battle with " << m_health << " health" << std::endl;
    else
      std::cout << m_name << "'s body is staying on the battleground" << std::endl;
  }

  void hit(int damage)
  {
    m_health -= damage;
    std::cout << m_name << " has recieved " << damage << " damage" << std::endl;
    if (m_health <= 0)
      std::cout << m_name << " is dead" << std::endl;
  }

  const std::string & name() const
  { return m_name; }
  std::string name()
  { return m_name; }

protected:

  void attack(Warrior &target, const std::string &message, int damage)
  {
    if (m_health > 0)
    {
      std::cout << message << std::endl;
      target.hit(damage);
    }
    else
    {
      std::cout << m_name << " is dead and can't attack " << target.name() << std::endl;
    }
  }

protected:

  std::string m_name;
  int m_health;

};

//////////////////////////////////////////////////////

class Spearman : public Warrior, public Spear<Warrior>
{
public:

  Spearman(const std::string name, int health):
    Warrior(name, health)
  { }

protected:

  virtual void spear(Warrior &w)
  {
    attack(w, m_name + " is throwing spear to " + w.name(), 10);
  }
};

//////////////////////////////////////////////////////

class Lancer : public Warrior, public Lance<Warrior>
{
public:

  Lancer(const std::string name, int health):
    Warrior(name, health)
  { }

protected:

  virtual void lance(Warrior &w)
  {
    attack(w, m_name + " is piercing " + w.name() + " by lance", 20);
  }
};

//////////////////////////////////////////////////////

class Hammerer : public Warrior, public Hammer<Warrior>
{
public:

  Hammerer(const std::string name, int health):
    Warrior(name, health)
  { }

protected:

  virtual void hammer(Warrior &w)
  {
    attack(w, m_name + " is crushing hammer on " + w.name(), 15);
  }
};

//////////////////////////////////////////////////////

class Macer : public Warrior, public Mace<Warrior>
{
public:

  Macer(const std::string name, int health):
    Warrior(name, health)
  { }

protected:

  virtual void mace(Warrior &w)
  {
    attack(w, m_name + " is beating " + w.name() + " by mace", 8);
  }
};

//////////////////////////////////////////////////////

class Merman: public Warrior, public Trident<Warrior>
{
public:

  Merman(const std::string name, int health):
    Warrior(name, health)
  { }

protected:

  virtual void trident(Warrior &w)
  {
    attack(w, m_name + " is striking " + w.name() + " with trident", 16);
  }
};

//////////////////////////////////////////////////////

class Thief: public Warrior, public Dagger<Warrior>
{
public:

  Thief(const std::string name, int health):
    Warrior(name, health)
  { }

protected:

  virtual void dagger(Warrior &w)
  {
    attack(w, m_name + " is backstabing " + w.name() + " by dagger", 16);
  }
};

//////////////////////////////////////////////////////

class Gunner: public Warrior, public Handgun<Warrior>
{
public:

  Gunner(const std::string name, int health):
    Warrior(name, health)
  { }

protected:

  virtual void handgun(Warrior &w)
  {
    attack(w, m_name + " is shooting " + w.name() + " from handgun at", 30);
  }
};

//////////////////////////////////////////////////////

class Bomber: public Warrior, public Bomb<Warrior>
{
public:

  Bomber(const std::string name, int health):
    Warrior(name, health)
  { }

protected:

  virtual void bomb(Warrior &w)
  {
    attack(w, m_name + " is blasting " + w.name(), 50);
  }
};


weapons.hpp
#pragma once

//////////////////////////////////
// Метательное копьё

template <typename T>
class Spear
{
public:
  typedef T Target;
  typedef Spear<T> This;

private:
  class Proxy
  {
  public:
    Proxy(This *p): m_this(p) { }
    void operator >(Target &t) { m_this->spear(t); }
  private:
    This *m_this;
  };

public:
  Proxy operator --(int) { return Proxy(this); }

protected:
  virtual void spear(Target &) = 0;
};

//////////////////////////////////
// Кавалерийское копьё

template <typename T>
class Lance
{
public:
  typedef T Target;
  typedef Lance<T> This;

  class Proxy1
  {
  public:
    Proxy1(This *p): m_this(p) { }
    void operator >(Target &t) { m_this->lance(t); }
  private:
    This *m_this;
  };

  class Proxy2
  {
  public:
    Proxy2(This *p): m_this(p) { }
    Proxy1 operator --(int) { return Proxy1(m_this); }
  private:
    This *m_this;
  };

public:
  Proxy2 operator --(int) { return Proxy2(this); }

protected:
  virtual void lance(Target &) = 0;
};

//////////////////////////////////////
// Молот

template <typename T>
class Hammer
{
public:
  typedef T Target;
  typedef Hammer<T> This;

private:

  class Proxy1
  {
  public:
    Proxy1(This *p): m_this(p) { }
    void operator -(Target &t) { m_this->hammer(t); }
  private:
    This *m_this;
  };

  class Proxy2
  {
  public:
    Proxy2(This *p): m_this(p) { }
    Proxy1 operator ()() { return Proxy1(m_this); }
  private:
    This *m_this;
  };

public:
  Proxy2 operator --(int) { return Proxy2(this); }

protected:
  virtual void hammer(Target &) = 0;
};

//////////////////////////////////////
// Булава

template <typename T>
class Mace
{
public:
  typedef T Target;
  typedef Mace<T> This;

private:

  class Proxy
  {
  public:
    Proxy(This *p): m_this(p) { }
    void operator *(Target &t) {  m_this->mace(t); }
  private:
    This *m_this;
  };

public:
  Proxy operator --(int) { return Proxy(this); }

protected:
  virtual void mace(Target &) = 0;
};

//////////////////////////////////////
// Трезубец

struct TridentPart { };
const TridentPart E = TridentPart();

template <typename T>
class Trident
{
public:
  typedef T Target;
  typedef Trident<T> This;

private:

  class Proxy1
  {
  public:
    Proxy1(This *p): m_this(p) { }
    void operator -(Target &t) { return m_this->trident(t); }
  private:
    This *m_this;
  };

  class Proxy2
  {
  public:
    Proxy2(This *p): m_this(p) { }
    Proxy1 operator -(const TridentPart &) { return Proxy1(m_this); }
  private:
    This *m_this;
  };

public:
  Proxy2 operator --(int) { return Proxy2(this); }

protected:
  virtual void trident(Target &) = 0;
};

//////////////////////////////////////
// Кинжал

template <typename T>
class Dagger
{
public:
  typedef T Target;
  typedef Dagger<T> This;

  struct Part
  {
    Part(Target *t): m_target(t) { }

    template <typename TT>
    Part(const TT &p): m_target(p.m_target) { }

    Target *m_target;
  };

public:
  void operator +(const Part &part) { dagger(*part.m_target); }

protected:
  virtual void dagger(Target &) = 0;
};

template <typename T>
typename Dagger<T>::Part operator -(T &t)
{
  return typename Dagger<T>::Part(&t);
}

//////////////////////////////////////
// Пистолет

template <typename T>
class Handgun
{
public:
  typedef T Target;
  typedef Handgun<T> This;

  struct Part
  {
    Part(Target *t): m_target(t) { }

    template <typename TT>
    Part(const TT &p): m_target(p.m_target) { }

    Target *m_target;
  };

public:
  void operator ,(const Part &part) { handgun(*part.m_target); }

protected:
  virtual void handgun(Target &) = 0;
};

template <typename T>
typename Handgun<T>::Part operator --(T &t)
{
  return typename Handgun<T>::Part(&t);
}

//////////////////////////////////////
// Бомба
template <typename T>
class Bomb
{
public:
  typedef T Target;
  typedef Bomb<T> This;

private:

  class Proxy1
  {
  public:
    Proxy1(This *p): m_this(p) { }
    void operator *(Target &t) { return m_this->bomb(t); }
  private:
    This *m_this;
  };

  class Proxy2
  {
  public:
    Proxy2(This *p): m_this(p) { }
    Proxy1 operator --(int) { return Proxy1(m_this); }
  private:
    This *m_this;
  };

public:
  Proxy2 operator ()() { return Proxy2(this); }

protected:
  virtual void bomb(Target &) = 0;
};
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.