Boost logo

Boost Users :

From: Black Ice (yg-boost-users_at_[hidden])
Date: 2003-08-06 02:19:23


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

Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net