boost::anyを実装してみる

C++テンプレートテクニック 7-3


boost::anyの話が出てきました。

なんでも格納できるクラスです。

とりあえず本を参考にしながら出来る範囲内で実装してみます。

#include <iostream>
using std::cout; using std::endl;

class any {
private:
    // 非テンプレート基本クラス
    struct _any_base {
        virtual ~_any_base() {}
        virtual const std::type_info& type () const = 0;
        virtual _any_base* clone() const = 0;
    };
    
    // テンプレート派生クラス
    template<class T>
    struct _any : public _any_base {
        T m_value;
        
        _any(T value) {
            m_value = value;
        }
        
        const std::type_info& type () const {
            return typeid(T);
        }
        
        _any_base* clone () const {
            return new _any<T>(m_value);
        }
        
        virtual ~_any() {}
    };
    
    _any_base* m_obj;

public:
    template<class T>
    any (const T& value) {
        m_obj = new _any<T>(value);
    }
    
    any (const any& obj) {
        if ( obj.m_obj ) {
            m_obj = obj.m_obj->clone();
        }
        else {
            m_obj = 0;
        }
    }
    
    any& operator=(const any& obj) {
        delete m_obj;
        if ( obj.m_obj ) {
            m_obj = obj.m_obj->clone();
        }
        else {
            m_obj = 0;
        }
        return *this;
    }
    
    template<class T>
    any& operator=(const T& value) {
        delete m_obj;
        m_obj = new _any<T>(value);
        return *this;
    }
    
    template<class T>
    const T& cast() const {
        return dynamic_cast< _any<T>& >(*m_obj).m_value;
    }
    
    const std::type_info& type () const {
        return m_obj->type();
    }
    
    ~any () {
        delete m_obj;
    }
    
};

class Foo {
public:
    const char* str() const {
        return "Foo";
    }
};

int main () {
    any a = 10;
    any b = a;
    
    cout << b.type().name() << endl;
    cout << b.cast<int>() << endl;
    
    b = Foo();
    
    cout << b.type().name() << endl;
    cout << b.cast<Foo>().str() << endl;
    
    return 0;
}
$ main
int
10
class Foo
Foo

やっと完成。とはいえほぼ本のままだけど。

typeidやconst周りでいろいろ躓いた。まだまだちゃんと理解してないので精進しなければ。