funnyクラスを作ってみた。その2

funnyの色々な使い方。

// メンバ関数を呼び出す。
template <class T,class U,class V,class W>
class speak_type:public U
{
  public:
  void speak() const
    {
      static_cast<const T*>(this)->data()->speak();
    }
  struct interface
    {
      virtual void speak() const=0;
    };
};


class dog
{
  public:
    void speak() const { std::cout << "わん\n"; }
};

class cat
{
  public:
    void speak() const { std::cout << "にゃ〜\n"; }
};

int main()
{
  dog pochi;
  cat tama;
  funny<speak_type> pet;	// メンバ関数speak()の呼出しが可能
  pet = pochi;
  pet.speak();
  pet = tama;
  pet.speak();
  return 0;
}
// キャストなしで出力可能にする。
template <class T,class U,class V,class W>
class output_type:public U
{
  public:
    friend std::ostream& operator<<(std::ostream& os, const T& x)
      {
        return x.data()->print(os);
      }
  std::ostream& print(std::ostream& os) const
    {
      return os << *(static_cast<const T*>(this)->data());
    }
  struct interface
    {
      virtual std::ostream& print(std::ostream& os) const = 0;
    };
};

int main()
{
  funny<output_type> x;
  x = 1;
  std::cout << x << std::endl;
  x = 3.1415;
  std::cout << x << std::endl;
  return 0;
}
//加算可能にする。
template <class T,class U,class V,class W>
class add_type:public U
{
  public:
  V& operator+=(const V& x)
    {
      static_cast<T*>(this)->typecheck(static_cast<const T&>(x));
      *(static_cast<T*>(this)->data())+=*(static_cast<const T&>(x).data());
      return *static_cast<T*>(this);
    }
  friend T operator+(const T& x, const T& y)
    {
      T tmp(x);
      return tmp+=y;
    }
  struct interface
    {
      virtual typename T::funny_imp_base& operator+=(const typename T::funny_imp_base&) = 0;
    };
};

int main()
{
  funny<add_type> x(1),y(2);
  std::cout << int(x+y) << std::endl;
  return 0;
}
// 型Sとの加算を可能にする。
template <class S>
class Add
{
  public:
template <class T,class U,class V,class W>
class type:public U
{
  public:
  W operator+(const S& x) const
    {
      return *(static_cast<const T*>(this)->data())+x;
    }
  friend W operator+(const S& x,const T& y)
    {
      return y.data()->addr(x);
    }
  W addr(const S& x) const
    {
      return x+*(static_cast<const T*>(this)->data());
    }
  struct interface
    {
      virtual W operator+(const S&) const = 0;
      virtual W addr(const S&) const = 0;
    };
};
};

int main()
{
  funny<Add<int>::type> a(3.4);
  std::cout << double(a+4) << std::endl;
}