
Larry wrote:
So if I had: struct sname_t { string first_m; string last_m; }; sname_t a_sname; a_sname.first_m="first"; a_sname.last_m="last"; then, to convert this to using typemaps, I would do: struct fname_t: public string{...}; struct lname_t: public string{...}; NS:type_map<fname_t,lname_t> mname_t; mname_t a_mname; a_mname = fname_t("first"); a_mname = lname_t("last"); So I don't see that I've gained much, at least in this case.
Firstly, I left too much of the fleshing out possible from the type_map abstraction implicit, which certainly left room for your question (sorry). Consider: a_mname = x.get_last_name(); Benefits include: * Code using type_maps can speculatively store values (with mismatches reported by the compiler) without needing to know specifics of the types or field identifiers: e.g. template <class FUNCTOR> ...(const FUNCTOR& functor)... a_mname = functor(x, y, z); * You can iterate over the fields. An implementation of the visitor pattern just calls an accept() method on the type_map_base templates wrapping each element, with the default for no_typeN being empty. This allows things like generic serialisation, assuming the fields/members/elements are serialisable. * You can enquire whether a particular type is in the map (the T* find<T> implementation if/elses through is_same<TN,T> tests, returning a pointer or 0). * Removal of the redundant field-name + implicit-type information inherent after evolving from the type-unsafe: a_sname.first_m = x.get_last_name(); to use of distinct types for fields, ensuring a match such as: a_sname.last_m = x.get_last_name(); Cheers, Tony P.S. Hope the following (228 lines) aren't considered excessive... #include <typeinfo> #include <boost/type_traits/is_same.hpp> namespace NS { namespace Private { class no_type1 { }; class no_type2 { }; class no_type3 { }; class no_type4 { }; template <typename T> class type_map_base { public: enum { COUNT = 1 }; void operator=(const T& t) { t_ = t; } operator const T&() const { return t_; } template <class VISITOR> void accept(const VISITOR& visitor) { visitor.on_visit(t_); } T* get_ptr() { return &t_; } const T* get_ptr() const { return &t_; } private: T t_; }; // have to explicitly incorporate apply_functor to retain EBCO w/ g++ template<> struct type_map_base<no_type1> { enum { COUNT = 0 }; template <class V> inline void accept(const V&) { } void* get_ptr() { return 0; } }; template<> struct type_map_base<no_type2> { enum { COUNT = 0 }; template <class V> inline void accept(const V&) { } void* get_ptr() { return 0; } }; template<> struct type_map_base<no_type3> { enum { COUNT = 0 }; template <class V> inline void accept(const V&) { } void* get_ptr() { return 0; } }; template<> struct type_map_base<no_type4> { enum { COUNT = 0 }; template <class V> inline void accept(const V&) { } void* get_ptr() { return 0; } }; } template <typename T0, typename T1 = Private::no_type1, typename T2 = Private::no_type2, typename T3 = Private::no_type3, typename T4 = Private::no_type4> class type_map : public Private::type_map_base<T0>, public Private::type_map_base<T1>, public Private::type_map_base<T2>, public Private::type_map_base<T3>, public Private::type_map_base<T4> { public: enum { COUNT = Private::type_map_base<T0>::COUNT + Private::type_map_base<T1>::COUNT + Private::type_map_base<T2>::COUNT + Private::type_map_base<T3>::COUNT + Private::type_map_base<T4>::COUNT }; typedef T0 type_1; typedef T1 type_2; typedef T2 type_3; typedef T3 type_4; typedef T4 type_5; template <typename VISITOR> void accept(const VISITOR& visitor) { visitor.on_before(); Private::type_map_base<T0>::accept(visitor); if (COUNT >= 2) { visitor.on_between(); Private::type_map_base<T1>::accept(visitor); if (COUNT >= 3) { visitor.on_between(); Private::type_map_base<T2>::accept(visitor); if (COUNT >= 4) { visitor.on_between(); Private::type_map_base<T3>::accept(visitor); if (COUNT >= 5) { visitor.on_between(); Private::type_map_base<T4>::accept(visitor); } } } } visitor.on_after(); } // return pointer to member else NULL template <typename T> T* find() { if (boost::is_same<T, T0>::value) return (T*)Private::type_map_base<T0>::get_ptr(); else if (boost::is_same<T, T1>::value) return (T*)Private::type_map_base<T1>::get_ptr(); else if (boost::is_same<T, T2>::value) return (T*)Private::type_map_base<T2>::get_ptr(); else if (boost::is_same<T, T3>::value) return (T*)Private::type_map_base<T3>::get_ptr(); else if (boost::is_same<T, T4>::value) return (T*)Private::type_map_base<T4>::get_ptr(); else return 0; } template <int N> const std::type_info& ct_get_type_info() const { switch(N) { case 0: return typeid(T0); case 1: return typeid(T1); case 2: return typeid(T2); case 3: return typeid(T3); case 4: return typeid(T4); default: return typeid(void); } } const std::type_info& rt_get_type_info(int n) const { switch(n) { case 0: return typeid(T0); case 1: return typeid(T1); case 2: return typeid(T2); case 3: return typeid(T3); case 4: return typeid(T4); default: return typeid(void); } } using Private::type_map_base<T0>::operator=; using Private::type_map_base<T1>::operator=; using Private::type_map_base<T2>::operator=; using Private::type_map_base<T3>::operator=; using Private::type_map_base<T4>::operator=; }; } #include <iostream> #include <string> using namespace std; class Printer { public: void on_before() const { cout << "{ "; } template <typename T> void on_visit(const T& t) const { cout << t; } void on_between() const { cout << ", "; } void on_after() const { cout << " }" << endl; } }; int main() { NS::type_map<int, float, string> tmid; tmid = 3; tmid = (float)2.71828; tmid = "hello"; string s = tmid; cout << "operator T(): " << (int)tmid << ' ' << (float)tmid << ' ' << s << endl; cout << "sizeof comparison: " << sizeof(tmid) << " vs " << sizeof(int) << '+' << sizeof(float) << '+' << sizeof(string) << endl; cout << "::COUNT " << NS::type_map<int, string>::COUNT << endl; cout << "Printing..." << endl; Printer printer; tmid.accept(printer); float* p_float = tmid.find<float>(); cout << "p_float " << p_float << endl; double* p_double = tmid.find<double>(); cout << "p_double " << p_double << endl; } ___________________________________________________________ To help you stay safe and secure online, we've developed the all new Yahoo! Security Centre. http://uk.security.yahoo.com