
Pls. look the source codde and demo code, you will find a good substitute for boost.tuple. Any suggestions are appreciated. Source code #ifndef _PROPERTYLIST_HEADER_ #define _PROPERTYLIST_HEADER_ namespace pl{ struct NullType { NullType() {} template<typename T> NullType(const T&) {} }; template<typename H, typename T> struct PropertyList { typedef H head_type; typedef T tail_type; typedef PropertyList<head_type, tail_type> my_type; PropertyList() : head_value(head_type()), tail_value(tail_type()) {} template<typename OtherHead, typename OtherTail> PropertyList(const OtherHead & head, const OtherTail & tail) : head_value(head), tail_value(tail) {} PropertyList(const my_type & other) : head_value(other.head_value), tail_value(other.tail_value) {} void swap(my_type & other) { std::swap(head_value, other.head_value); std::swap(tail_value, other.tail_value); } my_type & operator=(const my_type & other) { if(this != &other) { my_type temp(other); swap(temp); } return *this; } head_type head_value; tail_type tail_value; }; #define PROPERTYLIST_1(T1) PropertyList<T1, NullType> template<typename T1> PROPERTYLIST_1(T1) make_list(const T1 & t1) { return PROPERTYLIST_1(T1)(t1, NullType()); } #define PROPERTYLIST_2(T1, T2) PropertyList<T1, PROPERTYLIST_1(T2) > template<typename T1, typename T2> PROPERTYLIST_2(T1, T2) make_list(const T1 & t1, const T2 & t2) { return PROPERTYLIST_2(T1, T2)(t1, make_list(t2)); } #define PROPERTYLIST_3(T1, T2, T3) PropertyList<T1, PROPERTYLIST_2(T2, T3) > template<typename T1, typename T2, typename T3> PROPERTYLIST_3(T1, T2, T3) make_list(const T1 & t1, const T2 & t2, const T3 & t3) { return PROPERTYLIST_3(T1, T2, T3)(t1, make_list(t2, t3)); } #define PROPERTYLIST_4(T1, T2, T3, T4) PropertyList<T1, PROPERTYLIST_3(T2, T3, T4) > template<typename T1, typename T2, typename T3, typename T4> PROPERTYLIST_4(T1, T2, T3, T4) make_list(const T1 & t1, const T2 & t2, const T3 & t3, const T4 & t4) { return PROPERTYLIST_4(T1, T2, T3, T4)(t1, make_list(t2, t3, t4)); } #define PROPERTYLIST_5(T1, T2, T3, T4, T5) PropertyList<T1, PROPERTYLIST_4(T2, T3, T4, T5) > template<typename T1, typename T2, typename T3, typename T4, typename T5> PROPERTYLIST_5(T1, T2, T3, T4, T5) make_list(const T1 & t1, const T2 & t2, const T3 & t3, const T4 & t4, const T5 & t5) { return PROPERTYLIST_5(T1, T2, T3, T4, T5)(t1, make_list(t2, t3, t4, t5)); } #define PROPERTYLIST_6(T1, T2, T3, T4, T5, T6) PropertyList<T1, PROPERTYLIST_5(T2, T3, T4, T5, T6) > template<typename T1, typename T2, typename T3, typename T4, typename T5, typename T6> PROPERTYLIST_6(T1, T2, T3, T4, T5, T6) make_list(const T1 & t1, const T2 & t2, const T3 & t3, const T4 & t4, const T5 & t5, const T6 & t6) { return PROPERTYLIST_6(T1, T2, T3, T4, T5, T6)(t1, make_list(t2, t3, t4, t5, t6)); } #define PROPERTYLIST_7(T1, T2, T3, T4, T5, T6, T7) PropertyList<T1, PROPERTYLIST_6(T2, T3, T4, T5, T6, T7) > template<typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7> PROPERTYLIST_7(T1, T2, T3, T4, T5, T6, T7) make_list(const T1 & t1, const T2 & t2, const T3 & t3, const T4 & t4, const T5 & t5, const T6 & t6, const T7 & t7) { return PROPERTYLIST_7(T1, T2, T3, T4, T5, T6, T7)(t1, make_list(t2, t3, t4, t5, t6, t7)); } #define PROPERTYLIST_8(T1, T2, T3, T4, T5, T6, T7, T8) PropertyList<T1, PROPERTYLIST_7(T2, T3, T4, T5, T6, T7, T8) > template<typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8> PROPERTYLIST_8(T1, T2, T3, T4, T5, T6, T7, T8) make_list(const T1 & t1, const T2 & t2, const T3 & t3, const T4 & t4, const T5 & t5, const T6 & t6, const T7 & t7, const T8 & t8) { return PROPERTYLIST_8(T1, T2, T3, T4, T5, T6, T7, T8)(t1, make_list(t2, t3, t4, t5, t6, t7, t8)); } #define PROPERTYLIST_9(T1, T2, T3, T4, T5, T6, T7, T8, T9) PropertyList<T1, PROPERTYLIST_8(T2, T3, T4, T5, T6, T7, T8, T9) > template<typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8, typename T9> PROPERTYLIST_9(T1, T2, T3, T4, T5, T6, T7, T8, T9) make_list(const T1 & t1, const T2 & t2, const T3 & t3, const T4 & t4, const T5 & t5, const T6 & t6, const T7 & t7, const T8 & t8, const T9 & t9) { return PROPERTYLIST_9(T1, T2, T3, T4, T5, T6, T7, T8, T9)(t1, make_list(t2, t3, t4, t5, t6, t7, t8, t9)); } #define PROPERTYLIST_10(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10) PropertyList<T1, PROPERTYLIST_9(T2, T3, T4, T5, T6, T7, T8, T9, T10) > template<typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8, typename T9, typename T10> PROPERTYLIST_10(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10) make_list(const T1 & t1, const T2 & t2, const T3 & t3, const T4 & t4, const T5 & t5, const T6 & t6, const T7 & t7, const T8 & t8, const T9 & t9, const T10 & t10) { return PROPERTYLIST_10(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10)(t1, make_list(t2, t3, t4, t5, t6, t7, t8, t9, t10)); } template <class PList> struct Length { enum{value = 1 + Length<PList::tail_type>::value}; }; template <> struct Length<NullType> { enum{value = 0}; }; template<class PList, unsigned int N> struct TypeAt { typedef typename TypeAt<typename PList::tail_type, N-1>::type type; }; template<class PList> struct TypeAt<PList, 0> { typedef typename PList::head_type type; }; template<int N> struct TypeAt<NullType, N> { }; template<> struct TypeAt<NullType, 0> { typedef NullType type; }; template<class PList, class T> struct Append { typedef PropertyList<typename PList::head_type, typename Append< typename PList::tail_type, T>::type> type; }; template<class T> struct Append<NullType, T> { typedef PropertyList<T, NullType> type; }; template<class PList, class T> struct Push { typedef PropertyList<T, PList> type; }; template<class PList> struct Pop { typedef typename PList::tail_type type; }; template<class PList, unsigned int N> struct RemoveAt { typedef PropertyList<typename PList::head_type, typename RemoveAt<typename PList::tail_type, N-1>::type> type; }; template<class PList> struct RemoveAt<PList, 0> { typedef typename PList::tail_type type; }; template<int N> struct RemoveAt<NullType, N> { }; template<> struct RemoveAt<NullType, 0> { }; template<class PList, class T, unsigned int N> struct InsertAt { typedef PropertyList<typename PList::head_type, typename InsertAt<typename PList::tail_type, T, N-1>::type> type; }; template<class PList, class T> struct InsertAt<PList, T, 0> { typedef PropertyList<T, PList> type; }; template<class T, unsigned int N> struct InsertAt<NullType, T, N> { }; template<class T> struct InsertAt<NullType, T, 0> { }; template<class PList, unsigned int N> struct ValueAt { static typename TypeAt<PList, N>::type & get(PList & plist) { typedef typename PList::tail_type tail_type; tail_type & tail = plist.tail_value; return ValueAt<tail_type, N-1>::get(tail); } static const typename TypeAt<PList, N>::type & get(const PList & plist) { typedef const typename PList::tail_type tail_type; tail_type & tail = plist.tail_value; return ValueAt<tail_type, N-1>::get(tail); } }; template<class PList> struct ValueAt<PList, 0> { static typename TypeAt<PList, 0>::type & get(PList & plist) { return plist.head_value; } static const typename TypeAt<PList, 0>::type & get(const PList & plist) { return plist.head_value; } }; template<class PList, template<class> class FunctionClass, typename T = NullType> struct Visitor { static void for_each(PList & plist, T & t) { FunctionClass<typename PList::head_type> f(t); f(plist.head_value); typedef typename PList::tail_type tail_type; Visitor<tail_type, FunctionClass, T>::for_each(plist.tail_value, t); } }; template<class PList, template<class> class FunctionClass> struct Visitor<PList, FunctionClass, NullType> { static void for_each(PList & plist) { FunctionClass<typename PList::head_type>()(plist.head_value); typedef typename PList::tail_type tail_type; Visitor<tail_type, FunctionClass, NullType>::for_each(plist.tail_value); } }; template<template<class> class FunctionClass, typename T> struct Visitor<NullType, FunctionClass, T> { static void for_each(NullType & plist, T &) { } }; template<template<class> class FunctionClass> struct Visitor<NullType, FunctionClass, NullType> { static void for_each(NullType & plist) { } }; } // namespace pl #endif // _PROPERTYLIST_HEADER_ demo code #include <iostream> #include <string> #include <boost/type_traits.hpp> #include <PropertyList.h> #include <utility> using namespace std; using namespace boost; using namespace pl; template<typename T> struct Dump { void operator()(const T & t) { cout << t << endl; } }; template<typename T> struct LoadFromStream { LoadFromStream(long stream) : m_stream(stream) { } void operator()(T & t) { cout << "Load <" << t << "> from stream " << m_stream << endl; } long m_stream; }; template<typename PList> void SaveToStream(long stream, const PList & plist) { cout << "Save <" << plist.head_value << "> to stream " << stream << endl; SaveToStream(stream, plist.tail_value); } template<> void SaveToStream<NullType>(long stream, const NullType &) { } void test(void) { typedef PROPERTYLIST_3(int, long , double) MY_PROPS; BOOST_STATIC_ASSERT( (Length<MY_PROPS>::value == 3) ); BOOST_STATIC_ASSERT( (is_same<TypeAt<MY_PROPS, 0>::type, int>::value) ); BOOST_STATIC_ASSERT( (is_same<TypeAt<MY_PROPS, 1>::type, long>::value) ); BOOST_STATIC_ASSERT( (is_same<TypeAt<MY_PROPS, 2>::type, double>::value) ); BOOST_STATIC_ASSERT( (is_same<TypeAt<MY_PROPS, 3>::type, NullType>::value) ); typedef Append<MY_PROPS, float>::type MY_PROPS2; BOOST_STATIC_ASSERT( (Length<MY_PROPS2>::value == 4) ); BOOST_STATIC_ASSERT( (is_same<TypeAt<MY_PROPS2, 0>::type, int>::value) ); BOOST_STATIC_ASSERT( (is_same<TypeAt<MY_PROPS2, 1>::type, long>::value) ); BOOST_STATIC_ASSERT( (is_same<TypeAt<MY_PROPS2, 2>::type, double>::value) ); BOOST_STATIC_ASSERT( (is_same<TypeAt<MY_PROPS2, 3>::type, float>::value) ); BOOST_STATIC_ASSERT( (is_same<TypeAt<MY_PROPS2, 4>::type, NullType>::value) ); typedef Push<MY_PROPS, char>::type MY_PROPS3; BOOST_STATIC_ASSERT( (Length<MY_PROPS3>::value == 4) ); BOOST_STATIC_ASSERT( (is_same<TypeAt<MY_PROPS3, 0>::type, char>::value) ); BOOST_STATIC_ASSERT( (is_same<TypeAt<MY_PROPS3, 1>::type, int>::value) ); BOOST_STATIC_ASSERT( (is_same<TypeAt<MY_PROPS3, 2>::type, long>::value) ); BOOST_STATIC_ASSERT( (is_same<TypeAt<MY_PROPS3, 3>::type, double>::value) ); BOOST_STATIC_ASSERT( (is_same<TypeAt<MY_PROPS3, 4>::type, NullType>::value) ); typedef Pop<MY_PROPS>::type MY_PROPS4; BOOST_STATIC_ASSERT( (Length<MY_PROPS4>::value == 2) ); BOOST_STATIC_ASSERT( (is_same<TypeAt<MY_PROPS4, 0>::type, long>::value) ); BOOST_STATIC_ASSERT( (is_same<TypeAt<MY_PROPS4, 1>::type, double>::value) ); BOOST_STATIC_ASSERT( (is_same<TypeAt<MY_PROPS4, 2>::type, NullType>::value) ); typedef RemoveAt<MY_PROPS, 1>::type MY_PROPS5; BOOST_STATIC_ASSERT( (Length<MY_PROPS5>::value == 2) ); BOOST_STATIC_ASSERT( (is_same<TypeAt<MY_PROPS5, 0>::type, int>::value) ); BOOST_STATIC_ASSERT( (is_same<TypeAt<MY_PROPS5, 1>::type, double>::value) ); BOOST_STATIC_ASSERT( (is_same<TypeAt<MY_PROPS5, 2>::type, NullType>::value) ); typedef InsertAt<MY_PROPS, short, 1>::type MY_PROPS6; BOOST_STATIC_ASSERT( (Length<MY_PROPS6>::value == 4) ); BOOST_STATIC_ASSERT( (is_same<TypeAt<MY_PROPS6, 0>::type, int>::value) ); BOOST_STATIC_ASSERT( (is_same<TypeAt<MY_PROPS6, 1>::type, short>::value) ); BOOST_STATIC_ASSERT( (is_same<TypeAt<MY_PROPS6, 2>::type, long>::value) ); BOOST_STATIC_ASSERT( (is_same<TypeAt<MY_PROPS6, 3>::type, double>::value) ); BOOST_STATIC_ASSERT( (is_same<TypeAt<MY_PROPS6, 4>::type, NullType>::value) ); typedef Append<MY_PROPS, string>::type MY_PROPS7; MY_PROPS7 props; ValueAt<MY_PROPS7, 0>::get(props) = 1; ValueAt<MY_PROPS7, 1>::get(props) = 2; ValueAt<MY_PROPS7, 2>::get(props) = 3.3; ValueAt<MY_PROPS7, 3>::get(props) = "Hello World"; Visitor<MY_PROPS7, Dump>::for_each(props); long stream = 1; Visitor<MY_PROPS7, LoadFromStream, long>::for_each(props, stream); MY_PROPS7 props2 = make_list(10, 20L, 3.1415, string("Hello World")); SaveToStream(stream, props2); } -- Regards, Black Ice Çë²»Òª»ØžŽµœÎÒµÄÓÊÏä ×ÔÓÉ£šliberty£©ÎÞ·ÇŸÍÊÇÕâÑùÒ»ÖÖ³Ðŵ£ºÃ¿žöÈËœ«»áµÃµœÒ»ÖÖ±£ÕÏ£¬±£ÕÏÎÒÃÇ¿ÉÒÔÓë ÈšÍþ¡¢¶àÊý¡¢Á÷Ë׌°ÓßÂÛµÄÓ°ÏìÏ࿹ºâ¡£ http://www.leoliu.net