
AMDG "Marco Costalba" <mcostalba@gmail.com> wrote:
Sorry, but I don't understand, could you please post an example of how to use the dispatcher so to see 'struct implicit_conversion' at work ?
Thanks Marco
The code I posted was not well thought out. The set of implicit conversions should probably be global. I would want to write make_implicit_conversion<double, int>(); make_implicit_conversion<int, double>(); Somewhere during initialization to say that int is convertible to double and double to int. Here's a more complete implementation (warning untested) I'm not showing how to register functions. That would involve creating a function object that casts from void* to the actual type. A real implementation would probably also use Boost.Function instead of function pointers. struct wrap_typeinfo { friend bool operator<(const wrap_typeinfo& lhs, const wrap_typeinfo& rhs) { return(lhs.key.before(rhs.key)); } const std::type_info* impl; }; struct implicit_conversion { friend bool operator<(const implicit_conversion& lhs, const implicit_conversion& rhs) { return(lhs.from.before(rhs.from)); } const std::type_info* to; void* (*convert)(void*); void (*destroy)(void*); }; static std::multi_map<wrap_typeinfo, implicit_conversion> all_conversions; void* ignore_convert(void* x) { return(x); } void ignore_destroy(void*) {} static implicit_conversion no_conversion = { 0, 0, &ignore_convert &ignore_destroy }; template<class To> void destroy(void* victim) { delete static_cast<To*>(victim); } template<class From, class To> void* convert(void* from) { return new To(*static_cast<From*>(from)); } template<class From, class To> void make_implicit_conversion() { wrap_typeinfo from = { &typeid(From) }; implicit_conversion result = { &typeid(To), &convert<From, To>, &destroy<From, To> }; all_conversions.insert(std::make_pair(from, result)); } template<class R> struct dispatcher0 { public: R operator()() const { return(f0()); } private: R (*f0)(); }; template<class F> F get_function(F f, const std::type_info**, const implicit_conversion**) { return(f); } template<class F, class T> F get_function(const std::map<wrap_typeinfo, T>& m, wrap_typeinfo* types, const implicit_conversion** out) { std::map<wrap_typeinfo, T>::iterator iter = m.find(*types); if(iter != m.end()) { ++types; *out++ = &no_conversion; return(get_function<F>(t.value, types, out)); } else { BOOST_FOR_EACH(const implicit_conversion& conversion, all_conversions.equal_range(*types)) { std::map<wrap_typeinfo, T>::iterator iter = m.find(*conversion.from); if(iter != m.end()) { ++types; *out++ = &conversion; return(get_function<F>(iter->second, types, out)); } } } return(0); } template<int N> struct cleanup_array : cleanup_array<N - 1> { cleanup_array(implicit_conversion* c, void** data) : cleanup_array<N - 1>(c) { x = c[N - 1].convert(data[N-1]); } ~cleanup_array() { cleanup_array<N - 1>::conversions[N-1].destroy(x); } void* x; }; template<> struct cleanup_array<0> { implicit_conversion* conversions; cleanup_array(implicit_conversion* c, void**) : conversions(c) {} }; template<int N, int N2> void* get(cleanup_array<N2>& from) { return(static_cast<cleanup_array<N+1>&>(from).x); } template<class R> struct dispatcher1 { public: template<class T0> R operator()(T0 t0) const { wrap_typeinfo types[1] = { &typeid(T0) }; implicit_conversion* conversions[1]; R (*f)(void*) = get_function<R(*)(void*)>(f1, types, conversions); void* elements[1] = { &t0 }; cleanup_array<1> data(conversions, elements); return(f(get<0>(data))); } private: std::map<wrap_typeinfo, R(*)(void*)> f1; }; template<class R> struct dispatcher2 { public: template<class T0, class T1> R operator()(T0 t0, T1 t1) const { wrap_typeinfo types[2] = { &typeid(T0), &typeid(T2) }; implicit_conversion* conversions[2]; R (*f)(void*) = get_function<R(*)(void*, void*)>(f2, types, conversions); void* elements[2] = { &t0, &t1 }; cleanup_array<2> data(conversions, elements); return(f(get<0>(data), get<1>(data))); } private: std::map<wrap_typeinfo, std::map<wrap_typeinfo, R(*)(void*, void*)>
f2; };
In Christ, Steven Watanabe