Boost.TypeErasure any のコンストラクタで暗黙の呼び出しを行いたい
[追記]
この問題はリリース版である Boost 1.54.0 では動作するようになりました。
さて、Boost.TypeErasure any のコンストラクタでは explicit で定義されているため、次のように関数にコンセプトを満たす型を渡す場合、明示的に型変換を行なってから渡さなければいけません。
typedef boost::mpl::vector< boost::type_erasure::ostreamable<>, boost::type_erasure::addable<>, boost::type_erasure::copy_constructible<> > twice_disp_concept; void twice_disp(boost::type_erasure::any<twice_disp_concept> const& any){ std::cout << (any + any) << std::endl; } // error twice_disp(10); twice_disp(std::string("homu")); // ok twice_disp(boost::type_erasure::any<twice_disp_concept>(10)); twice_disp(boost::type_erasure::any<twice_disp_concept>(std::string("homu")));
これだとちょっと使い勝手が悪いので、any をラップして explicit でない any を定義してみました。
[ソース]
#include <boost/type_erasure/any.hpp> #include <boost/type_erasure/operators.hpp> #include <boost/mpl/vector.hpp> template<class Concept, class T = boost::type_erasure::_self> struct non_explicit_any : boost::type_erasure::any<Concept, T>{ typedef boost::type_erasure::any<Concept, T> base_type; using boost::type_erasure::any<Concept, T>::any; template<typename U> non_explicit_any(U&& u) : base_type(std::forward<U>(u)){} // Inheriting constructors が未実装の場合 // template<typename ...Args> // non_explicit_any(Args&&... args) // : base_type(std::forward<Args>(args)...){} }; typedef boost::mpl::vector< boost::type_erasure::ostreamable<>, boost::type_erasure::addable<>, boost::type_erasure::copy_constructible<> > twice_disp_concept; void twice_disp(non_explicit_any<twice_disp_concept> const& any){ std::cout << (any + any) << std::endl; } #include <vector> #include <iostream> #include <string> #include <boost/range/algorithm/for_each.hpp> struct X{ int value; }; std::ostream& operator <<(std::ostream& os, X const& x){ return os << x.value; } X operator +(X const& a, X const& b){ return { a.value + b.value }; } int main(){ // ok twice_disp(non_explicit_any<twice_disp_concept>(10)); twice_disp(non_explicit_any<twice_disp_concept>(std::string("homu"))); twice_disp(non_explicit_any<twice_disp_concept>(X{42})); // ok twice_disp(10); twice_disp(std::string("homu")); twice_disp(X{42}); return 0; }
[出力]
20 homuhomu 84 20 homuhomu 84
思ったよりも痒いところに手が届きそうなので便利そう。