#眉標=Boost #副標=「Boost技術與應用」系列文章(3) #大標= Array和Any #作者=文/侯捷 ==本文相關資訊 =========== • 讀者基礎:擁有C++ templates編程經驗與C++標準程式庫使用經驗。 • 本文測試環境:VC6(+)。 • 本系列文章將匯整至編寫中的《Boost運用與源碼剖析》一書。 ================ ==<反黑>=========== int myIntArray[100]; //定義一個array,可容納100個ints ================ ==程式1 class block =========== template 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 ================ ==程式2 class c_array =========== template 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 ================ ==程式3 class carray =========== template 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 ================ ==程式4 boost::array關鍵源碼 =========== template 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) ================ ==程式5 BOOST_ASSERT源碼=========== #undef BOOST_ASSERT #if defined(BOOST_DISABLE_ASSERTS) # define BOOST_ASSERT(expr) ((void)0) #elif defined(BOOST_ENABLE_ASSERT_HANDLER) #include 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 // .h to support old libraries w/o - effect is the same # define BOOST_ASSERT(expr) assert(expr) #endif (取自\boost\include\boost-1_33\boost\assert.hpp) ================ ==程式6 測試Boost.Array =========== #include #include #include #include using namespace std; using namespace boost; template 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 Array; Array a = { 42 }; for (unsigned i=1; i a = { 1, 2, 3, 4, 5 }; print_elements(a); //1 2 3 4 5 0 0 0 0 0 //直接改動元素 for (unsigned i=0; i()); //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; } ================ ==程式7 =========== //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 ================ ==<反黑>=========== vector v; v.push_back(Derived()); v.push_back(MostDerived()); ... ================ ==<反黑>=========== vector 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() ... ================ ==程式8 指定容器的元素型別為any並放入6個異型物=========== using namespace std; using namespace boost; ... vector 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); ================ ==程式9 =========== void print_any(any& a) { if (A* pA = any_cast(&a)) { pA->func(); } else if (B* pB = any_cast(&a)) { pB->func(); } else if (C* pC = any_cast(&a)) { pC->func(); } else { try { cout << any_cast(a) << endl; } catch (bad_any_cast&) { cout << "bad any cast!" << endl; } } } ================ ==程式10 =========== class any { public: template any(const T & value) //non-explicit, one-argument建構式 : content(new holder(value)) { } ... ~any() { delete content; } private: placeholder* content; }; ================ ==程式11 =========== class placeholder { public: virtual ~placeholder() { } public: // queries virtual const std::type_info & type() const = 0; virtual placeholder* clone() const = 0; }; ================ ==程式12 =========== template class holder : public placeholder { public: holder(const T & value) : held(value) { } ... public: T held; }; ================ == <反黑>=========== //版本一 template T* any_cast(any* operand) { return operand && operand->type() == typeid(T) ? &static_cast*>(operand->content)->held : 0; } ================ ==<反黑>=========== operand->type() == typeid(T) ================ ==<反黑>=========== &static_cast*>(operand->content)->held ================ ============= holder是定義於any內的一個private嵌套類別,而any_cast被定義為any的一個friend,所以any_cast()內可使用any::holder。如果編譯器不支援template friend,Boost就把holder定義為any內的一個public嵌套類別,那麼更是任何人都可以直接使用any::holder。 ================ ==<反黑>=========== //版本二 template const T* any_cast(const any* operand) { return any_cast(const_cast(operand)); } //使用版本一 ================ ==<反黑>=========== //版本三 template T any_cast(const any& operand) { typedef remove_reference::type nonref; const nonref* result = any_cast(&operand); //使用版本二 if(!result) boost::throw_exception(bad_any_cast()); return *result; } ================ ==<反黑>=========== //版本四 template T any_cast(any& operand) { typedef remove_reference::type nonref; nonref* result = any_cast(&operand); //使用版本一 if(!result) boost::throw_exception(bad_any_cast()); return *result; } ================ ==更多資訊 =========== 以下是與本文相關的讀物或網上資源。 • 《Beyond the C++ Standard Library, An Introduction to Boost》by Bjorn Karlesson, A.W. 2005. • Boost Libraries Documentation, from http://www.boost.org ================ ==作者簡介 =========== 侯捷 資訊顧問、專欄主筆、大學執教。常著文章自娛,頗示己志。 侯捷網站:http://www.jjhou.com(繁體) 北京鏡站:http://jjhou.csdn.net(簡體) 永久郵箱:jjhou@jjhou.com ================