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


思ったよりも痒いところに手が届きそうなので便利そう。