#眉標=Boost
#副標=「Boost技術與應用」系列文章(3)
#大標= Array和Any
#作者=文/侯捷



==本文相關資訊	<box>===========
‧ 讀者基礎:擁有C++ templates編程經驗與C++標準程式庫使用經驗。
‧ 本文測試環境:VC6(+)。
‧ 本系列文章將匯整至編寫中的《Boost運用與源碼剖析》一書。
==<end>==============



==<反黑>===========
int myIntArray[100]; //定義一個array,可容納100個ints
==<end>==============




==程式1		class block <box>===========
template <class T, size_t N>
struct block {
  typedef T 					value_type;
  typedef value_type* 			pointer;
  typedef value_type& 			reference;
  typedef ptrdiff_t 			difference_type;
  typedef size_t 				size_type;
  typedef pointer 			iterator;

  reference operator[](size_type n) { return data[n]; }
  iterator begin() { return data; }
  iterator end() { return data + N; }
  size_type size() const { return N; }

  T data[N];
};

註:取自《Generic Programming and the STL》,p.60~p.61
==<end>==============



==程式2		class c_array <box>===========
template<class T, int max>
struct c_array {
  typedef T 			value_type;
  typedef T* 		iterator;
  typedef T& 		reference;

  operator T*() { return v; }
  reference operator[](size_t i) { return v[i]; }
  iterator begin() { return v; }
  iterator end() { return v + thesize; }
  size_type size() const { return thesize; }

  T v[max];  
};

註:取自《The C++ Programming Language》3/e, p.496
==<end>==============



==程式3		class carray <box>===========
template<class T, std::size_t thesize>
class carray {
public:
  typedef T 				value_type;
  typedef T* 			iterator;
  typedef T& 			reference;
  typedef std::size_t 		size_type;
  typedef std::ptrdiff_t 	difference_type;

  reference operator[](std::size_t i) { return v[i]; }
  iterator begin() { return v; }
  iterator end() { return v + thesize; }
  size_type size() const { return thesize; }
  size_type max_size() const { return thesize; }
  T* as_array() { return v; }

private:
  T v[thesize]; // fixed-size array of elements of type T   
};

註:取自《The C++ Standard Library》, p.219
==<end>==============




==程式4		boost::array關鍵源碼 <box>===========
    template<class T, std::size_t N>
    class array {
      public:
        T elems[N];    // fixed-size array of elements of type T

      public:
        // type definitions
        typedef T              	value_type;
        typedef T*             	iterator;
        typedef const T*     	const_iterator;
        typedef T&             	reference;
        typedef const T&  		const_reference;
        typedef std::size_t  	size_type;
        typedef std::ptrdiff_t 	difference_type;
    
        // iterator support
        iterator begin() { return elems; }
        iterator end() { return elems+N; }

        reference operator[](size_type i) 
        { 
            BOOST_ASSERT( i < N && "out of range" ); 
            return elems[i];
        }
        reference at(size_type i) { 
            rangecheck(i); return elems[i]; 
        }

        reference front()   { 
            return elems[0]; 
        }        
        reference back()   { 
            return elems[N-1]; 
        }        
        static size_type size() { return N; }
        static bool empty() { return false; }
        static size_type max_size() { return N; }
        enum { static_size = N };

        // direct access to data (read-only)
        const T* data() const { return elems; }
        // use array as C array (direct read/write access to data)
        T* c_array() { return elems; }

        // check range (may be private because it is static)
        static void rangecheck (size_type i) {
            if (i >= size()) { 
                throw std::range_error("array<>: index out of range");
            }
        }
    }; 

(摘自 \boost\include\boost-1_33\boost\array.hpp)
==<end>==============




==程式5		BOOST_ASSERT源碼<box>===========
#undef BOOST_ASSERT
#if defined(BOOST_DISABLE_ASSERTS)
# define BOOST_ASSERT(expr) ((void)0)                                
#elif defined(BOOST_ENABLE_ASSERT_HANDLER)
#include <boost/current_function.hpp>                                  
namespace boost                                                            
{                                                                             
void assertion_failed(char const * expr,                               
                          char const * function,                           
                          char const * file,                               
                          long line); // user defined                     
} // namespace boost                                                       
#define BOOST_ASSERT(expr) ((expr)? ((void)0):                        
                  ::boost::assertion_failed(#expr,                      
                                                  BOOST_CURRENT_FUNCTION, 
                                                  __FILE__,                 
                                                  __LINE__))                                 
#else
# include <assert.h>                                                       
    // .h to support old libraries w/o <cassert> - effect is the same
# define BOOST_ASSERT(expr) assert(expr)                              
#endif

(取自\boost\include\boost-1_33\boost\assert.hpp)
==<end>==============



==程式6		測試Boost.Array <box>===========
#include <iostream>
#include <boost/array.hpp>
#include <algorithm>
#include <functional>

using namespace std;
using namespace boost;

template <class T>
inline void print_elements (const T& coll, const char* optcstr="")
{
    typename T::const_iterator pos;   //使用const iterator為佳

    cout << optcstr;            	//先輸出optional string
    for (pos=coll.begin(); pos!=coll.end(); ++pos) {
        cout << *pos << ' ';   	//逐一輸出元素
    }
    cout << endl;
}

int main()
{
    { //以下測試來自解壓縮後所得的 \boost_1_33_0\libs\array\array1.cpp
    typedef boost::array<float,6> Array;
    Array a = { 42 }; 

    for (unsigned i=1; i<a.size(); ++i) {
        a[i] = a[i-1]+1;
    }
    //使用若干常見的STL容器操作函式
    cout << "size:     " << a.size() << endl;  	//6
    cout << "empty:    " << (a.empty() ? "true" : "false") << endl;
    cout << "max_size: " << a.max_size() << endl;	//6
    cout << "front:    " << a.front() << endl;		//42
    cout << "back:     " << a.back() << endl;		//47
    cout << "elems:    ";

    //迭代穿越所有元素
    for (Array::const_iterator pos=a.begin(); pos<a.end(); ++pos) {
        cout << *pos << ' ';
    }
    cout << endl;		//42 43 44 45 46 47

    //檢驗copy ctor和copy op=
    Array b(a);  //喚起copy ctor
    Array c;
    c = a;        //喚起copy op=
    if (a==b && a==c) {
        cout << "copy ctor and copy op= are OK" << endl;
    }
    else {
        cout << "copy ctor and copy op= FAILED" << endl;
    }
    } //scope1

    { //以下測試來自解壓縮後所得的\boost_1_33_0\libs\array\array2.cpp
    array<int,10> a = { 1, 2, 3, 4, 5 }; 
    print_elements(a);    	//1 2 3 4 5 0 0 0 0 0

    //直接改動元素
    for (unsigned i=0; i<a.size(); ++i) {
        ++a[i];			
    }
    print_elements(a);      //2 3 4 5 6 1 1 1 1 1

    //運用STL algorithm改變元素次序
    reverse(a.begin(),a.end());
    print_elements(a);		//1 1 1 1 1 6 5 4 3 2

    //運用STL algorithm改變元素內容(全部加上負號)
    transform(a.begin(),a.end(),    	//source
                a.begin(),            	//destination
                negate<int>());       	//operation
    print_elements(a);		//-1 -1 -1 -1 -1 -6 -5 -4 -3 -2

	//! cout << a.at(10) << endl;  //abnormal program termination
	//! cout << a[10] << endl;  	 //Assertion failed: i < N && "out of range",…
    } //scope2

    return 0; 
}
==<end>==============




==程式7		<box>===========
//in Boost\include\boost-1_33\boost \current_function.hpp
namespace boost
{
namespace detail
{
inline void current_function_helper()
{
#if defined(__GNUC__) || (defined(__MWERKS__) && (__MWERKS__ >= 0x3000)) || (defined(__ICC) && (__ICC >= 600))
# define BOOST_CURRENT_FUNCTION __PRETTY_FUNCTION__
#elif defined(__FUNCSIG__)
# define BOOST_CURRENT_FUNCTION __FUNCSIG__
#elif (defined(__INTEL_COMPILER) && (__INTEL_COMPILER >= 600)) || (defined(__IBMCPP__) && (__IBMCPP__ >= 500))
# define BOOST_CURRENT_FUNCTION __FUNCTION__
#elif defined(__BORLANDC__) && (__BORLANDC__ >= 0x550)
# define BOOST_CURRENT_FUNCTION __FUNC__
#elif defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901)
# define BOOST_CURRENT_FUNCTION __func__
#else
# define BOOST_CURRENT_FUNCTION "(unknown)"
#endif
}
} // namespace detail
} // namespace boost
==<end>==============





==<反黑>===========
vector<Base> v;
v.push_back(Derived());
v.push_back(MostDerived());
...
==<end>==============




==<反黑>===========
vector<void*> v;
v.push_back((void*)new classA);
v.push_back((void*)new classB);
v.push_back((void*)new classC);
    //以上各元素有無強制轉型為(void*)無所謂,都可通過編譯且無警告。
((classA*)vv[0])->func();  //喚起classA::func()
((classB*)vv[1])->func();  //喚起classB::func()
((classC*)vv[2])->func();  //喚起classC::func()
...
==<end>==============





==程式8		指定容器的元素型別為any並放入6個異型物<box>===========
using namespace std;
using namespace boost;
  ...
  vector<any> va;
  va.push_back(A());
  va.push_back(B());
  va.push_back(C());
  va.push_back(string("a test string"));
  va.push_back(10);
  va.push_back(make_pair(true,9.28));
  for_each(va.begin(), va.end(), print_any);
==<end>==============





==程式9		<box>===========
void print_any(any& a)
{
  if (A* pA = any_cast<A>(&a)) {
      pA->func();
  }
  else if (B* pB = any_cast<B>(&a)) {
      pB->func();
  }
  else if (C* pC = any_cast<C>(&a)) {        
      pC->func();
  }
  else {
    try {
      cout << any_cast<string>(a) << endl;   
    }
    catch (bad_any_cast&) {
      cout << "bad any cast!" << endl;
    }
  }
}
==<end>==============





==程式10	<box>===========
    class any
    {
    public: 
        template<typename T>
        any(const T & value)     //non-explicit, one-argument建構式
          : content(new holder<T>(value))  {   } 
        ...
        ~any() { delete content; }
   private:
        placeholder* content;
    };
==<end>==============




==程式11	<box>===========
        class placeholder
        {
        public: 
            virtual ~placeholder()   {    }
        public: // queries
            virtual const std::type_info & type() const = 0;
            virtual placeholder* clone() const = 0;  
        };
==<end>==============




==程式12	<box>===========
        template<typename T>
        class holder : public placeholder
        {
        public: 
            holder(const T & value)
              : held(value)   {  }
            ...
        public: 
            T held;
        };
==<end>==============




== <反黑>===========
//版本一
template<typename T>
T* any_cast(any* operand)
{
  return operand && operand->type() == typeid(T)
   ? &static_cast<any::holder<T>*>(operand->content)->held
   : 0;
}
==<end>==============



==<反黑>===========
  operand->type() == typeid(T)
==<end>==============



==<反黑>===========
   &static_cast<any::holder<T>*>(operand->content)->held
==<end>==============




==<box>===========
holder是定義於any內的一個private嵌套類別,而any_cast被定義為any的一個friend,所以any_cast()內可使用any::holder。如果編譯器不支援template friend,Boost就把holder定義為any內的一個public嵌套類別,那麼更是任何人都可以直接使用any::holder。
==<end>==============



==<反黑>===========
//版本二
template<typename T>
const T* any_cast(const any* operand)
{ return any_cast<T>(const_cast<any*>(operand));   } //使用版本一
==<end>==============




==<反黑>===========
//版本三
template<typename T>
T any_cast(const any& operand)
{
   typedef remove_reference<T>::type nonref;
   const nonref* result = any_cast<nonref>(&operand); //使用版本二
   if(!result)   boost::throw_exception(bad_any_cast());
   return *result;
}
==<end>==============



==<反黑>===========
//版本四
template<typename T>
T any_cast(any& operand)
{
    typedef remove_reference<T>::type nonref;
    nonref* result = any_cast<nonref>(&operand); //使用版本一
    if(!result)   boost::throw_exception(bad_any_cast());
    return *result;
}
==<end>==============




==更多資訊	<box>===========
以下是與本文相關的讀物或網上資源。
‧ 《Beyond the C++ Standard Library, An Introduction to Boost》by Bjorn Karlesson, A.W. 2005.
‧ Boost Libraries Documentation, from http://www.boost.org
==<end>==============

==作者簡介	<box>===========
侯捷
資訊顧問、專欄主筆、大學執教。常著文章自娛,頗示己志。
侯捷網站:http://www.jjhou.com(繁體)
北京鏡站:http://jjhou.csdn.net(簡體)
永久郵箱:jjhou@jjhou.com 
==<end>==============