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

boostのfunctionとanyを合わせたようなクラスを作ってみた。
対応コンパイラは、VCとGCCのみ。
variadic templatesの使用推奨。

簡単な使用例。

#include <iostream>
#include <cstdlib>
#include "funny.h"

int main()
{
  funny<> x;
  x = 1;
  std::cout << (int)x << std::endl;
  x = 3.1415;
  std::cout << (double)x << std::endl;
  funny<func<double(const char*)>::type> f = &std::atof;
  std::cout << f("1.2345") << std::endl;
  return 0;
}

以下実装。

// funny.h
#if defined(_MSC_VER)
#pragma  warning(disable:4250)
#endif
#include <typeinfo>
#include <stdexcept>
#include <algorithm>
#ifdef __GXX_EXPERIMENTAL_CXX0X__
#define VT
#endif
template <class T>
struct remove_const
{ typedef T type; };
template <class T>
struct remove_const<const T>
{ typedef T type; };

class bad_call:public std::exception{};
template <class T,class U,class V,class W>
struct any_type;

class null_type{};
#ifdef VT
#define ___ ...
#else
#define ___ 
#endif
#ifdef VT
template <class D, class B, class V, class W, template<class,class,class,class>class ... T>
class IMPS;
template <class D, class B,class V, class W>
class IMPS<D,B,V,W>:public any_type<D,B,V,W>{};
template <class D, class B,class V, class W, template<class,class,class,class>class T>
class IMPS<D,B,V,W,T>:public T<D,B,V,W>{};
template <class D, class B,class V, class W, template<class,class,class,class>class T, template<class,class,class,class>class ... U>
class IMPS<D,B,V,W,T,U ...>:public IMPS<D,IMPS<D,B,V,W,T>,V,W,U ...>{};
#else
template <class D, class B,class V, class W, template<class,class,class,class>class T>
class IMPS:public T<D,B,V,W>{};
#endif

#ifdef VT
template <template <class,class,class,class>class ... T>
#else
template <template <class,class,class,class>class T=any_type>
#endif
class funny:public IMPS<funny<T ___>,null_type,funny<T ___>,funny<T ___>,T ___>
{
public:
class funny_imp_base:public T<funny,null_type,funny,funny>::interface ___
{
  public:
    virtual funny_imp_base* create() const=0;
    virtual const std::type_info& type() const = 0;
};
private:
template <class S>
class funny_imp:public IMPS<funny_imp<S>,funny_imp_base,funny_imp_base,funny, T ___>
{
    template <template<class,class,class,class> class ___ U> friend class funny;
  public:
    funny_imp(const S& x): data_(x){}
    funny_imp* create() const
      { return new funny_imp(data_); }
    const std::type_info& type() const
      { return typeid(S); }
    void typecheck(const funny_imp_base&) const { }
    const S* data() const { return &data_; }
          S* data()       { return &data_; }
  private:
    S data_;

};


  public:
    funny():data_(){}
    template <class U>
    funny(const U& x): data_(new funny_imp<U>(x)){}
    template <class U>
    funny& operator=(const U& x)
      { delete data_;data_ = new funny_imp<U>(x); return *this; }
    funny& operator=(const funny& x)
      {
        if(this != &x)
          { funny tmp(x); swap(tmp); }
        return *this;
      }
    funny(const funny& x)
      {
        if(x.data_) data_ = x.data_->create();
        else        data_ = 0;
      }
    template <class U> operator const U&() const
      {
        if(funny_imp<U>* p = dynamic_cast<funny_imp<U>*>(data_))
          return *p->data();
        throw std::bad_cast();
      }
    template <class U> operator U&()
      {
        if(funny_imp<typename remove_const<U>::type>* p
            = dynamic_cast<funny_imp<typename remove_const<U>::type>*>(data_))
          return *const_cast<U*>(p->data());
        throw std::bad_cast();
      }
    ~funny(){delete data_;}
    void swap(funny& x)
      { std::swap(data_, x.data_); }
    bool empty() const
      { return !data_; }
    void clear()
      { delete data_; data_ = 0; }
    const std::type_info& type() const
      {
        if(!data_) return typeid(void);
        return data_->type();
      }
    void typecheck(const funny& x) const
      {
        if(type() != x.type())
          throw bad_call();
      }
    funny_imp_base* data() const
      {
        if(!data_) throw bad_call();
        return data_;
      }
  private:
    funny_imp_base* data_;
};

template <class T,class U,class V,class W>
struct any_type:public U
{ struct interface{}; };

template <class T>
class func;
template <class R, class ___ A>
class func<R(A ___)>
{
    #ifdef VT
    template <int N, class... S> struct GET
      { typedef void type; };
    template <class S, class... U>
    struct GET<1,S,U...>
      { typedef S type; };
    template <int N, class S, class... U>
    struct GET<N,S,U...>
      { typedef typename GET<N-1,U...>::type type; };
    #endif

public:
  template <class T, class U,class V,class W>
  class type:public U
  {
    public:
    typedef R result_type;
  #ifndef VT
    typedef A argument_type;
  #else
    template <int N>
    struct argument{ typedef typename GET<N,A...>::type type; };
    typedef typename argument<1>::type        argument_type;
    typedef typename argument<1>::type  first_argument_type;
    typedef typename argument<2>::type second_argument_type;
  #endif
    R operator() (A ___ x) const
      {
        return (*static_cast<const T*>(this)->data())(x ___);
      }
    struct interface
      {
        virtual R operator()(A ___) const=0;
      };
  };
};