俺俺any
C++のboostにあるboost::anyってご存知でしょうか?
なんでも放りこめる便利な型です(詳細はこの辺でも)
しかし、boost::anyを使っててたまーに困るのが共変の型でも変換できないということがあります。
具体的には
struct X{int value;}; struct Y:X{}; boost::any a = Y(); //aにはY型が入っている X x = boost::any_cast<X>(a);//Y型はX型ではないので変換できない!
このようにY型とX型が継承の関係にあっても違う型なので変換できません。
とっても悔しいです。あきらかにY型からX型への変換は問題はないというのに!
なんとか解決したくなったので超適当に本質部分だけ実装してany_cast
#include<iostream> #include<boost/any.hpp> struct any_e{ struct any_handler{virtual ~any_handler(){}virtual void exec()=0;}; template<typename T> struct any_impl : any_handler{T value; void exec(){throw value;} any_impl(const T&value):value(value){} }; any_handler*handler; template<typename T> any_e(T value):handler(new any_impl<T>(value)){} }; template<typename T> T any_cast(any_e&e){ try{ e.handler->exec(); }catch(const T&r){ return r; } throw "BAD CAST"; } int main(){ struct X{int value;}; struct Y:X{}; try{ any_e a((Y())); X x = any_cast<X>(a); std::cout << "OK any_e\n"; }catch(...){ std::cout << "NG any_e\n"; } try{ boost::any a((Y())); X x = boost::any_cast<X>(a); std::cout << "OK any\n"; }catch(...){ std::cout << "NG any\n"; } }
これで共変の型ならany_castが出来たー。
継承を捉えるのに例外を使って補足しました。上の実装はあくまでコンセプトだけなので実装は超絶手抜きですが。
ところでこれとっても重いんで誰かもっとスマートな実装あったら教えてください