首先看一下bind.hpp中的list0模板定義:
[cpp]
class list0
{
public:
list0() {}
template<class T> T & operator[] (_bi::value<T> & v) const { return v.get(); }
template<class T> T const & operator[] (_bi::value<T> const & v) const { return v.get(); }
template<class T> T & operator[] (reference_wrapper<T> const & v) const { return v.get(); }
template<class R, class F, class L> typename result_traits<R, F>::type operator[] (bind_t<R, F, L> & b) const { return b.eval(*this); }
template<class R, class F, class L> typename result_traits<R, F>::type operator[] (bind_t<R, F, L> const & b) const { return b.eval(*this); }
template<class R, class F, class A> R operator()(type<R>, F & f, A &, long)
{
return unwrapper<F>::unwrap(f, 0)();
}
template<class R, class F, class A> R operator()(type<R>, F const & f, A &, long) const
{
return unwrapper<F const>::unwrap(f, 0)();
}
template<class F, class A> void operator()(type<void>, F & f, A &, int)
{
unwrapper<F>::unwrap(f, 0)();
}
template<class F, class A> void operator()(type<void>, F const & f, A &, int) const
{
unwrapper<F const>::unwrap(f, 0)();
}
template<class V> void accept(V &) const
{
}
bool operator==(list0 const &) const
{
return true;
}
};
提供了accept方法接受V&,但是什麼實現也沒有。提供了一堆operator重載函數,重點關注operator()()的函數,說明其實list0就是一個function object。
1.type<R>是什麼?定義如下:
[cpp] www.2cto.com
template<class T> class type {};
只是一個普通模板,接受任何類型。
2.unwrap(f,0)的結果是返回f, 因此如果f是以一個函數傳遞給了operator()(type<R>, F& f, A&, long) ,則內部的unwrap(f,0)返回的是f
因此實際上代碼被編譯成了直接調用f的代碼:f()
這是個很好的讓編譯器在編譯期產生調用函數代碼的技巧。
因此功能比較強大。
3.實際上f函數執行的時候傳遞進來的參數這裡是空,下面就能看到有一個參數的例子。
繼續看list1的定義:
template< class A1 > class list1: private storage1< A1 >
{
private:
typedef storage1< A1 > base_type;
public:
explicit list1( A1 a1 ): base_type( a1 ) {}
A1 operator[] (boost::arg<1>) const { return base_type::a1_; }
A1 operator[] (boost::arg<1> (*) ()) const { return base_type::a1_; }
template<class T> T & operator[] ( _bi::value<T> & v ) const { return v.get(); }
template<class T> T const & operator[] ( _bi::value<T> const & v ) const { return v.get(); }
template<class T> T & operator[] (reference_wrapper<T> const & v) const { return v.get(); }
template<class R, class F, class L> typename result_traits<R, F>::type operator[] (bind_t<R, F, L> & b) const { return b.eval(*this); }
template<class R, class F, class L> typename result_traits<R, F>::type operator[] (bind_t<R, F, L> const & b) const { return b.eval(*this); }
template<class R, class F, class A> R operator()(type<R>, F & f, A & a, long)
{
return unwrapper<F>::unwrap(f, 0)(a[base_type::a1_]);
}
template<class R, class F, class A> R operator()(type<R>, F const & f, A & a, long) const
{
return unwrapper<F const>::unwrap(f, 0)(a[base_type::a1_]);
}
template<class F, class A> void operator()(type<void>, F & f, A & a, int)
{
unwrapper<F>::unwrap(f, 0)(a[base_type::a1_]);
}
template<class F, class A> void operator()(type<void>, F const & f, A & a, int) const
{
unwrapper<F const>::unwrap(f, 0)(a[base_type::a1_]);
}
template<class V> void accept(V & v) const
{
base_type::accept(v);
}
bool operator==(list1 const & rhs) const
{
return ref_compare(base_type::a1_, rhs.a1_, 0);
}
};
看到很多老朋友了吧?
1.從storage1<A1>繼承,
因此也就擁有了a1_, 這裡有點不明白,為什麼偏特化版本的storag1沒有定義a1_,只有a1()靜態函數,居然這裡就有了。下面的代碼編譯通過。
[cpp]
boost::_bi::storage1<boost::arg<1> > x(_1);
x.a1_;
2. 幾個operator[]() 函數有點意思,用_1作為下標,調用的是第一個重載:
[cpp]
list[_1];
-->
A1 operator[] (boost::arg<1>) const { return base_type::a1_; }
3.operator()()函數的參數A & a實際上也是一個list1<A1 &>對象,並且裡面的a_成員就是外部實際調用的參數。
a[base_type::a1_] 這句代碼要注意:
通過this對象的base_type::a1_,這時候a1_是指針函數,返回占位符boost::arg<1> 。
用a1_來作為參數,傳遞給a對象的operator[](boost::arg<1> (*)() 方法來獲取內部保存的實際參數。
a對象和this對象都是一個從模板list1<>演化而來,但是不是同一個對象。
4.其他的函數都比較簡單, accept以前也介紹過,visitor模式的實現。