由于boost::lambda用了boost::tuple。
那么对tuple关键的代码进行分析。
tuple的使用很方面,也很简单,比如:
boost::tuple<int,double,string> triple(42, 3.245, "The amazing tuple!");
int a0 = triple.get<0>();
double a1 = triple.get<1>();
string a2 = triple.get<2>();
tuple的源码如下:
// -- tuple ------------------------------------------------------
template <class T0, class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class T9> class tuple : public detail::map_tuple_to_cons<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9>::type {
public: typedef typename detail::map_tuple_to_cons<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9>::type inherited;
typedef typename inherited::head_type head_type;
typedef typename inherited::tail_type tail_type; // access_traits<T>::parameter_type takes non-reference types as const T& tuple() {} tuple(typename access_traits<T0>::parameter_type t0) : inherited(t0, detail::cnull(), detail::cnull(), detail::cnull(), detail::cnull(), detail::cnull(), detail::cnull(), detail::cnull(), detail::cnull(), detail::cnull()) {}
tuple(typename access_traits<T0>::parameter_type t0, typename access_traits<T1>::parameter_type t1) : inherited(t0, t1, detail::cnull(), detail::cnull(), detail::cnull(), detail::cnull(), detail::cnull(), detail::cnull(), detail::cnull(), detail::cnull()) {} tuple(typename access_traits<T0>::parameter_type t0, typename access_traits<T1>::parameter_type t1, typename access_traits<T2>::parameter_type t2) : inherited(t0, t1, t2, detail::cnull(), detail::cnull(), detail::cnull(), detail::cnull(), detail::cnull(), detail::cnull(), detail::cnull()) {}
tuple(typename access_traits<T0>::parameter_type t0, typename access_traits<T1>::parameter_type t1, typename access_traits<T2>::parameter_type t2, typename access_traits<T3>::parameter_type t3) : inherited(t0, t1, t2, t3, detail::cnull(), detail::cnull(), detail::cnull(), detail::cnull(), detail::cnull(), detail::cnull()) {}
tuple(typename access_traits<T0>::parameter_type t0, typename access_traits<T1>::parameter_type t1, typename access_traits<T2>::parameter_type t2, typename access_traits<T3>::parameter_type t3, typename access_traits<T4>::parameter_type t4) : inherited(t0, t1, t2, t3, t4, detail::cnull(), detail::cnull(), detail::cnull(), detail::cnull(), detail::cnull()) {}
tuple(typename access_traits<T0>::parameter_type t0, typename access_traits<T1>::parameter_type t1, typename access_traits<T2>::parameter_type t2, typename access_traits<T3>::parameter_type t3, typename access_traits<T4>::parameter_type t4, typename access_traits<T5>::parameter_type t5) : inherited(t0, t1, t2, t3, t4, t5, detail::cnull(), detail::cnull(), detail::cnull(), detail::cnull()) {}
tuple(typename access_traits<T0>::parameter_type t0, typename access_traits<T1>::parameter_type t1, typename access_traits<T2>::parameter_type t2, typename access_traits<T3>::parameter_type t3, typename access_traits<T4>::parameter_type t4, typename access_traits<T5>::parameter_type t5, typename access_traits<T6>::parameter_type t6) : inherited(t0, t1, t2, t3, t4, t5, t6, detail::cnull(), detail::cnull(), detail::cnull()) {}
tuple(typename access_traits<T0>::parameter_type t0, typename access_traits<T1>::parameter_type t1, typename access_traits<T2>::parameter_type t2, typename access_traits<T3>::parameter_type t3, typename access_traits<T4>::parameter_type t4, typename access_traits<T5>::parameter_type t5, typename access_traits<T6>::parameter_type t6, typename access_traits<T7>::parameter_type t7) : inherited(t0, t1, t2, t3, t4, t5, t6, t7, detail::cnull(), detail::cnull()) {} tuple(typename access_traits<T0>::parameter_type t0, typename access_traits<T1>::parameter_type t1, typename access_traits<T2>::parameter_type t2, typename access_traits<T3>::parameter_type t3, typename access_traits<T4>::parameter_type t4, typename access_traits<T5>::parameter_type t5, typename access_traits<T6>::parameter_type t6, typename access_traits<T7>::parameter_type t7, typename access_traits<T8>::parameter_type t8) : inherited(t0, t1, t2, t3, t4, t5, t6, t7, t8, detail::cnull()) {}
tuple(typename access_traits<T0>::parameter_type t0, typename access_traits<T1>::parameter_type t1, typename access_traits<T2>::parameter_type t2, typename access_traits<T3>::parameter_type t3, typename access_traits<T4>::parameter_type t4, typename access_traits<T5>::parameter_type t5, typename access_traits<T6>::parameter_type t6, typename access_traits<T7>::parameter_type t7, typename access_traits<T8>::parameter_type t8, typename access_traits<T9>::parameter_type t9) : inherited(t0, t1, t2, t3, t4, t5, t6, t7, t8, t9) {} template<class U1, class U2> tuple(const cons<U1, U2>& p) : inherited(p) {}
template <class U1, class U2> tuple& operator=(const cons<U1, U2>& k) { inherited::operator=(k); return *this;
} template <class U1, class U2> tuple& operator=(const std::pair<U1, U2>& k) { BOOST_STATIC_ASSERT(length<tuple>::value == 2);// check_length = 2 this->head = k.first; this->tail.head = k.second; return *this;
}
}; // The empty tuple template <> class tuple<null_type, null_type, null_type, null_type, null_type, null_type, null_type, null_type, null_type, null_type> : public null_type { public: typedef null_type inherited; };
其中tuple继承map_tuple_to_cons是这个类很关键的角色,它之所以能够存放类型和类型对应
的变量(这个类是由cons类完成的)就是因为这个原因。
而map_tuple_to_cons的实现方式也值得研究:
template <class T0, class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class T9> struct map_tuple_to_cons { typedef cons<T0, typename map_tuple_to_cons<T1, T2, T3, T4, T5, T6, T7, T8, T9, null_type>::type > type; }; // The empty tuple is a null_type template <> struct map_tuple_to_cons<null_type, null_type, null_type, null_type, null_type, null_type, null_type, null_type, null_type, null_type> { typedef null_type type; };
这个类,如果用cons来描述,展开的形式如下:
cons<T0,cons<T1,cons<T2,cons<T3,cons<T4,cons<T5,cons<T6,cons<T7,cons<T8,cons<T9,null_type>>>>>>>>>>
这样的形式才能形成模板递归。在《Modern C++ Design》这本书前面的章节,有许多关于这方面的讨论。
形式上基本一样,不过tuple数据结构含有类型对应的变量。这点与书上不同的地方。
访问元素的方式同书上一样。
上面的inherited的类型是cons是一个嵌套的递归模板方式,因此构造函数的调用是调用:
template <class HT, class TT> struct cons {
typedef HT head_type;
typedef TT tail_type;
typedef typename detail::wrap_non_storeable_type<head_type>::type stored_head_type; stored_head_type head;
tail_type tail;
typename access_traits<stored_head_type>::non_const_type get_head() { return head; } typename access_traits<tail_type>::non_const_type get_tail() { return tail; }
typename access_traits<stored_head_type>::const_type get_head() const { return head; } typename access_traits<tail_type>::const_type get_tail() const { return tail; } cons() : head(), tail() {} // cons() : head(detail::default_arg<HT>::f()), tail() {}
// the argument for head is not strictly needed, but it prevents
// array type elements. This is good, since array type elements
// cannot be supported properly in any case (no assignment,
// copy works only if the tails are exactly the same type, ...)
cons(typename access_traits<stored_head_type>::parameter_type h, const tail_type& t) : head (h), tail(t) {}
template <class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class T9, class T10> cons( T1& t1, T2& t2, T3& t3, T4& t4, T5& t5, T6& t6, T7& t7, T8& t8, T9& t9, T10& t10 ) : head (t1), tail (t2, t3, t4, t5, t6, t7, t8, t9, t10, detail::cnull()) {}
template <class T2, class T3, class T4, class T5, class T6, class T7, class T8, class T9, class T10> cons( const null_type& /*t1*/, T2& t2, T3& t3, T4& t4, T5& t5, T6& t6, T7& t7, T8& t8, T9& t9, T10& t10 ) : head (), tail (t2, t3, t4, t5, t6, t7, t8, t9, t10, detail::cnull()) {} template <class HT2, class TT2> cons( const cons<HT2, TT2>& u ) : head(u.head), tail(u.tail) {}
template <class HT2, class TT2> cons& operator=( const cons<HT2, TT2>& u ) { head=u.head; tail=u.tail; return *this; }
// must define assignment operator explicitly, implicit version is // illformed if HT is a reference (12.8. (12)) cons& operator=(const cons& u) { head = u.head; tail = u.tail; return *this; } template <class T1, class T2> cons& operator=( const std::pair<T1, T2>& u ) { BOOST_STATIC_ASSERT(length<cons>::value == 2);
// check length = 2 head = u.first; tail.head = u.second; return *this; } // get member functions (non-const and const) template <int N> typename access_traits< typename element<N, cons<HT, TT> >::type >::non_const_type get() { return boost::tuples::get<N>(*this); // delegate to non-member get } template <int N> typename access_traits< typename element<N, cons<HT, TT> >::type >::const_type get() const { return boost::tuples::get<N>(*this); // delegate to non-member get } };
template <class HT> struct cons<HT, null_type> { typedef HT head_type;
typedef null_type tail_type; typedef cons<HT, null_type> self_type;
typedef typename detail::wrap_non_storeable_type<head_type>::type stored_head_type; stored_head_type head;
typename access_traits<stored_head_type>::non_const_type get_head() { return head; } null_type get_tail() { return null_type(); }
typename access_traits<stored_head_type>::const_type get_head() const { return head; } const null_type get_tail() const { return null_type(); } // cons() : head(detail::default_arg<HT>::f()) {}
cons() : head() {}
cons(typename access_traits<stored_head_type>::parameter_type h, const null_type& = null_type()) : head (h) {}
template<class T1> cons(T1& t1, const null_type&, const null_type&, const null_type&, const null_type&, const null_type&, const null_type&, const null_type&, const null_type&, const null_type&) : head (t1) {}
cons(const null_type&, const null_type&, const null_type&, const null_type&, const null_type&, const null_type&, const null_type&, const null_type&, const null_type&, const null_type&) : head () {}
template <class HT2> cons( const cons<HT2, null_type>& u ) : head(u.head) {} template <class HT2> cons& operator=(const cons<HT2, null_type>& u ) { head = u.head; return *this; } // must define assignment operator explicitely, implicit version // is illformed if HT is a reference cons& operator=(const cons& u) { head = u.head; return *this; } template <int N> typename access_traits< typename element<N, self_type>::type >::non_const_type get(BOOST_EXPLICIT_TEMPLATE_NON_TYPE(int, N)) { return boost::tuples::get<N>(*this);
}
template <int N> typename access_traits< typename element<N, self_type>::type >::const_type get(BOOST_EXPLICIT_TEMPLATE_NON_TYPE(int, N)) const { return boost::tuples::get<N>(*this);
}
};
上面的代码特别注意构造函数的调用方式,会递归的调用的构造函数。
其它同书上代码一样。而head实际上就是存放的变量,tail是末尾类型的变量,即可能是嵌套
模板对象也可能是单个元素(类型)对象(最后)。通过递归的方式,把所有的类型及变量变得可以访问。