Boost.Spiritの中にあるhold_anyにストリーム演算子があるのを思い出して、もしかして型安全操作書けるんじゃないかなーと思って書いてみた。
とりあえず関数ひとつ指定できるようにしただけで、any_castも何もできませんが、今後なにかおもしろいことを思いつくかもしれません。関数オブジェクトのfusion::mapを簡単に指定できるようにすればいいのかもしれない。
#include <iostream> #include "any.hpp" #include <boost/phoenix.hpp> struct disper { template <class T> void operator()(const T& x) const { std::cout << x << std::endl; } }; namespace phx = boost::phoenix; using phx::arg_names::_1; int main() { // 中に入ってる値を表示する { shand::any x(1, disper()); x.invoke(); } // 中に入ってる値を抽出する { int extract = 0; shand::any x(3, (phx::ref(extract) = _1)); x.invoke(); disper()(extract); } }
1 3
#ifndef SHAND_ANY_INCLUDE #define SHAND_ANY_INCLUDE #include <algorithm> #include <typeinfo> #include <boost/assert.hpp> namespace shand { class any { public: any() : content(0) { } template<typename ValueType, typename F> any(const ValueType& value, F f) : content(new holder<ValueType, F>(value, f)) { } any(const any& other) : content(other.content ? other.content->clone() : 0) { } ~any() { delete content; } public: any& swap(any& rhs) { std::swap(content, rhs.content); return *this; } template<typename ValueType> any& operator=(const ValueType& rhs) { any(rhs).swap(*this); return *this; } any& operator=(any rhs) { rhs.swap(*this); return *this; } public: bool empty() const { return !content; } void invoke() { BOOST_ASSERT(content); content->invoke(); } private: class placeholder { public: virtual ~placeholder() {} virtual placeholder* clone() const = 0; virtual void invoke() = 0; }; template<typename ValueType, typename F> class holder : public placeholder { public: holder(const ValueType& value, F f) : held(value), f(f) { } virtual placeholder* clone() const { return new holder(held, f); } virtual void invoke() { f(held); } public: ValueType held; F f; private: holder& operator=(const holder&); }; public: placeholder* content; }; } // namespace shand #endif // SHAND_ANY_INCLUDE