読者です 読者をやめる 読者になる 読者になる

Boost.TypeErasure のミニマム実装

C++ Boost

その昔に書いたコードを発掘したので載せてみるなど。
このコードは Boost.TypeErasure がリリースされた頃に書いたので、現在の実装はまた別のものになっているかも知れない。

[コード]

#include <iostream>
#include <boost/any.hpp>


template<typename Concept, typename T>
struct adapter{
    static void apply(boost::any const& any){
        Concept::apply(boost::any_cast<T>(any));
    }
};


template<typename Concept>
struct any{
    typedef void(*applicative_type)(boost::any const&);

    template<typename T>
    any(T const& t)
        : data(t)
        , applicative(&adapter<Concept, T>::apply)
    {}

    void
    apply(){
        applicative(data);
    }

private:
    boost::any data;
    applicative_type applicative;
};


struct ostreamable{
    template<typename T>
    static void apply(T const& t){
        std::cout << t << std::endl;
    }
};

struct functionable{
    template<typename T>
    static void apply(T const& t){
        t();
    }
};


struct X{
    X(int value) : value(value){}
    
    void
    operator ()() const{
        std::cout << value << std::endl;
    }

    int value;
};

std::ostream&
operator <<(std::ostream& os, X const& x){
    return os << x.value;
}


int
main(){
    any<ostreamable> i = 10;
    i.apply();
    
    X x = 42;
    any<ostreamable> x_any = x;
    x_any.apply();
    
    any<functionable> func = [](){ std::cout << "homu" << std::endl; };
    func.apply();

    any<functionable> x_func = x;
    x_func.apply();

    return 0;
}

[出力]

10
42
homu
42

まぁなんというか、なるほどなーというコード。
adapter<Concept, T>::apply 内でキャストを行うことで、any 内からは元の型にはアクセスしなくてもいいような構造になっています。
実際には演算子からの呼び出しや戻り値型も考慮しているのでもっと複雑になってる(はず。
しかし、よくこんなの思いつくよなぁ。