safearray.h

Go to the documentation of this file.
00001 00004 /* 00005 * Copyright © 2000, 2001, 2002 Sofus Mortensen, Michael Geddes 00006 * 00007 * This material is provided "as is", with absolutely no warranty 00008 * expressed or implied. Any use is at your own risk. Permission to 00009 * use or copy this software for any purpose is hereby granted without 00010 * fee, provided the above notices are retained on all copies. 00011 * Permission to modify the code and to distribute modified code is 00012 * granted, provided the above notices are retained, and a notice that 00013 * the code was modified is included with the above copyright notice. 00014 * 00015 * This header is part of comet. 00016 * http://www.lambdasoft.dk/comet 00017 */ 00018 00019 #ifndef COMET_SAFEARRAY_H 00020 #define COMET_SAFEARRAY_H 00021 00022 #include <iterator> 00023 00024 #include <comet/config.h> 00025 #include <comet/ptr.h> 00026 #include <comet/bstr.h> 00027 #include <comet/variant.h> 00028 #include <comet/static_assert.h> 00029 //#include <comet/util.h> 00030 #include <comet/type_traits.h> 00031 #include <comet/common.h> 00032 #include <comet/uuid.h> 00033 #ifndef NDEBUG 00034 #define COMET_ITERATOR_DEBUG 00035 #endif 00036 00037 namespace comet { 00038 00039 00040 namespace impl { 00041 00042 template <bool is_class> 00043 struct access_operator 00044 { 00045 // Has operator -> 00046 template <typename T, typename C> 00047 struct base 00048 { 00049 T *operator->() 00050 { 00051 return &(static_cast<C *>(this)->operator*()); 00052 } 00053 }; 00054 }; 00055 // Doesn't have operator-> 00056 template<> 00057 struct access_operator<false> 00058 { 00059 template <typename T, typename C> 00060 struct base 00061 { 00062 }; 00063 }; 00064 00065 template<typename T> struct sa_traits; //Moved to common.h 00066 00067 template<typename T, typename TR> class sa_iterator; 00068 00069 template<typename T> struct const_traits { 00070 typedef T value_type; 00071 typedef typename sa_traits<T>::const_reference reference; 00072 typedef const T* pointer; 00073 }; 00074 00075 template<typename T> struct nonconst_traits { 00076 typedef T value_type; 00077 typedef typename sa_traits<T>::reference reference; 00078 typedef T* pointer; 00079 }; 00080 00081 00082 template<> struct sa_traits<long> : public basic_sa_traits<long, VT_I4> {}; 00083 template<> struct sa_traits<unsigned long> : public basic_sa_traits<unsigned long, VT_UI4> {}; 00084 00085 template<> struct sa_traits<short> : public basic_sa_traits<short, VT_I2> {}; 00086 template<> struct sa_traits<unsigned short> : public basic_sa_traits<unsigned short, VT_UI2> {}; 00087 00088 template<> struct sa_traits<signed char> : public basic_sa_traits<signed char, VT_I1> {}; 00089 template<> struct sa_traits<unsigned char> : public basic_sa_traits<unsigned char, VT_UI1> {}; 00090 template<> struct sa_traits<char> : public basic_sa_traits<char, VT_I1> {}; 00091 00092 template<> struct sa_traits<float> : public basic_sa_traits<float, VT_R4> {}; 00093 template<> struct sa_traits<double> : public basic_sa_traits<double, VT_R8> {}; 00094 00095 template<> struct sa_traits<variant_t> 00096 { 00097 typedef VARIANT raw; 00098 00099 enum { vt = VT_VARIANT }; 00100 enum { check_type = impl::stct_features_ok }; 00101 enum { extras_type = stet_null }; 00102 00103 typedef variant_t value_type; 00104 typedef variant_t& reference; 00105 typedef const variant_t& const_reference; 00106 00107 static reference create_reference(raw& x) { return *reinterpret_cast<variant_t*>(&x); } 00108 static const_reference create_const_reference(raw& x) { return *reinterpret_cast<const variant_t*>(&x); } 00109 00110 typedef sa_iterator<variant_t, nonconst_traits<variant_t> > iterator; 00111 typedef sa_iterator<variant_t, const_traits<variant_t> > const_iterator; 00112 00113 static bool are_features_ok(unsigned short f) { return (f & FADF_VARIANT) != 0; } 00114 static com_ptr<IRecordInfo> get_record_info() { return 0; } 00115 }; 00116 00117 template<> struct sa_traits<bstr_t> 00118 { 00119 enum { vt = VT_BSTR }; 00120 enum { check_type = impl::stct_vt_ok }; 00121 enum { extras_type = stet_null }; 00122 00123 typedef BSTR raw; 00124 typedef bstr_t value_type; 00125 typedef bstr_t& reference; 00126 typedef const bstr_t& const_reference; 00127 00128 static reference create_reference(raw& x) { return *reinterpret_cast<bstr_t*>(&x); } 00129 static const_reference create_const_reference(raw& x) { return *reinterpret_cast<const bstr_t*>(&x); } 00130 00131 typedef sa_iterator<bstr_t, nonconst_traits<bstr_t> > iterator; 00132 typedef sa_iterator<bstr_t, const_traits<bstr_t> > const_iterator; 00133 00134 static bool are_features_ok(unsigned short f) { return (f & FADF_BSTR) != 0; } 00135 static com_ptr<IRecordInfo> get_record_info() { return 0; } 00136 }; 00137 00138 template<> struct sa_traits<currency_t> 00139 { 00140 enum { vt = VT_CY }; 00141 enum { check_type = impl::stct_vt_ok }; 00142 enum { extras_type = impl::stet_null }; 00143 00144 typedef CY raw; 00145 typedef currency_t value_type; 00146 typedef currency_t& reference; 00147 typedef const currency_t& const_reference; 00148 00149 static reference create_reference(raw& x) { return *reinterpret_cast<currency_t*>(&x); } 00150 static const_reference create_const_reference(raw& x) { return *reinterpret_cast<const currency_t*>(&x); } 00151 00152 typedef sa_iterator<currency_t, nonconst_traits<currency_t> > iterator; 00153 typedef sa_iterator<currency_t, const_traits<currency_t> > const_iterator; 00154 00155 static bool are_features_ok(unsigned short) { return true; } 00156 static com_ptr<IRecordInfo> get_record_info() { return 0; } 00157 }; 00158 00159 template<> struct sa_traits<datetime_t> 00160 { 00161 enum { vt = VT_DATE }; 00162 enum { check_type = impl::stct_vt_ok }; 00163 enum { extras_type = impl::stet_null }; 00164 00165 typedef DATE raw; 00166 typedef datetime_t value_type; 00167 typedef datetime_t& reference; 00168 typedef const datetime_t& const_reference; 00169 00170 static reference create_reference(raw& x) { return *reinterpret_cast<datetime_t*>(&x); } 00171 static const_reference create_const_reference(raw& x) { return *reinterpret_cast<const datetime_t*>(&x); } 00172 00173 typedef sa_iterator<datetime_t, nonconst_traits<datetime_t> > iterator; 00174 typedef sa_iterator<datetime_t, const_traits<datetime_t> > const_iterator; 00175 00176 static bool are_features_ok(unsigned short) { return true; } 00177 static com_ptr<IRecordInfo> get_record_info() { return 0; } 00178 }; 00179 00180 template<> struct sa_traits<variant_bool_t> 00181 { 00182 enum { vt = VT_BOOL }; 00183 enum { check_type = impl::stct_vt_ok }; 00184 enum { extras_type = impl::stet_null }; 00185 00186 typedef VARIANT_BOOL raw; 00187 typedef variant_bool_t value_type; 00188 typedef variant_bool_t& reference; 00189 typedef const variant_bool_t& const_reference; 00190 00191 static reference create_reference(raw& x) { return *reinterpret_cast<variant_bool_t*>(&x); } 00192 static const_reference create_const_reference(raw& x) { return *reinterpret_cast<const variant_bool_t*>(&x); } 00193 00194 typedef sa_iterator<variant_bool_t, nonconst_traits<variant_bool_t> > iterator; 00195 typedef sa_iterator<variant_bool_t, const_traits<variant_bool_t> > const_iterator; 00196 00197 static bool are_features_ok(unsigned short) { return true; } 00198 static com_ptr<IRecordInfo> get_record_info() { return 0; } 00199 }; 00200 00201 template<> struct sa_traits<bool>: sa_traits<variant_bool_t> 00202 { 00203 }; 00204 00205 template<> struct sa_traits< com_ptr< ::IUnknown> > 00206 { 00207 enum { vt = VT_UNKNOWN }; 00208 enum { check_type = impl::stct_vt_ok }; 00209 enum { extras_type = impl::stet_iid }; 00210 00211 typedef IUnknown* raw; 00212 typedef com_ptr< ::IUnknown> value_type; 00213 typedef com_ptr< ::IUnknown>& reference; 00214 typedef const com_ptr< ::IUnknown>& const_reference; 00215 00216 static reference create_reference(raw& x) { return *reinterpret_cast<com_ptr< ::IUnknown>*>(&x); } 00217 static const_reference create_const_reference(raw& x) { return *reinterpret_cast<const com_ptr< ::IUnknown>*>(&x); } 00218 00219 typedef sa_iterator<com_ptr< ::IUnknown >, nonconst_traits<com_ptr< ::IUnknown > > > iterator; 00220 typedef sa_iterator<com_ptr< ::IUnknown >, const_traits<com_ptr< ::IUnknown > > > const_iterator; 00221 00222 static bool are_features_ok(unsigned short f) { return (f & (FADF_UNKNOWN|FADF_DISPATCH)) != 0; } 00223 static com_ptr<IRecordInfo> get_record_info() { return 0; } 00224 static const uuid_t& iid() { return uuid_t::create_const_reference(IID_IUnknown); } 00225 }; 00226 00227 template<> struct sa_traits< com_ptr< ::IDispatch> > 00228 { 00229 enum { vt = VT_DISPATCH }; 00230 enum { check_type = impl::stct_vt_ok }; 00231 enum { extras_type = impl::stet_iid }; 00232 00233 typedef IDispatch* raw; 00234 typedef com_ptr< ::IDispatch> value_type; 00235 typedef com_ptr< ::IDispatch>& reference; 00236 typedef const com_ptr< ::IDispatch>& const_reference; 00237 00238 static reference create_reference(raw& x) { return *reinterpret_cast<com_ptr< ::IDispatch>*>(&x); } 00239 static const_reference create_const_reference(raw& x) { return *reinterpret_cast<const com_ptr< ::IDispatch>*>(&x); } 00240 00241 typedef sa_iterator<com_ptr< ::IDispatch>, nonconst_traits<com_ptr< ::IDispatch> > > iterator; 00242 typedef sa_iterator<com_ptr< ::IDispatch>, const_traits<com_ptr< ::IDispatch> > > const_iterator; 00243 00244 static bool are_features_ok(unsigned short f) { return (f & FADF_DISPATCH) != 0; } 00245 static com_ptr<IRecordInfo> get_record_info() { return 0; } 00246 00247 static const uuid_t& iid() { return uuid_t::create_const_reference(IID_IDispatch); } 00248 }; 00249 00250 #ifdef COMET_ITERATOR_DEBUG 00251 #define COMET_SAIT_THIS ,this 00252 #define COMET_SAIT_ITER(CONT_, IT_, TRAITS_) impl::sa_debug_iterator<CONT_, TRAITS_ > 00253 00254 template<typename TRAITS> 00255 struct sa_debug_traits 00256 { 00257 typedef TRAITS traits; 00258 typedef typename TRAITS::value_type value_type; 00259 typedef typename TRAITS::raw raw; 00260 typedef typename TRAITS::reference reference; 00261 typedef typename TRAITS::iterator nonconst_iterator; 00262 typedef typename TRAITS::iterator iterator; 00263 typedef typename TRAITS::const_iterator const_iterator; 00264 }; 00265 template<typename TRAITS> 00266 struct sa_const_debug_traits 00267 { 00268 typedef TRAITS traits; 00269 typedef typename TRAITS::value_type value_type; 00270 typedef typename TRAITS::raw raw; 00271 typedef typename TRAITS::const_reference reference; 00272 typedef typename TRAITS::iterator nonconst_iterator; 00273 typedef typename TRAITS::const_iterator iterator; 00274 typedef typename TRAITS::const_iterator const_iterator; 00275 }; 00276 00277 template< typename CONT, typename TRAITS> 00278 class sa_debug_iterator : public std::iterator<std::random_access_iterator_tag, typename TRAITS::value_type>, 00279 public access_operator<type_traits::is_class_pointer<typename TRAITS::value_type>::result>::base<typename TRAITS::raw, sa_debug_iterator<CONT,TRAITS> > 00280 { 00281 public: 00282 const CONT *cont_; 00283 typename TRAITS::iterator iter_; 00284 00285 template<typename IT> 00286 sa_debug_iterator(IT ptr, const CONT *cont) : iter_(ptr), cont_(cont) {} 00287 00288 sa_debug_iterator( const sa_debug_iterator<CONT, impl::sa_debug_traits<typename TRAITS::traits> > &nc_it ) : iter_(nc_it.iter_), cont_(nc_it.cont_) {} 00289 00290 sa_debug_iterator(): cont_(NULL) {} 00291 00292 typename TRAITS::iterator get_raw()const { return iter_; } 00293 typename TRAITS::const_iterator get_const_raw()const { return iter_; } 00294 00295 00296 sa_debug_iterator operator++(int) { 00297 COMET_ASSERT( cont_!=NULL); 00298 COMET_ASSERT( get_const_raw() < cont_->end().get_raw() ); 00299 sa_debug_iterator t(*this); 00300 ++iter_; 00301 return t; 00302 } 00303 00304 sa_debug_iterator& operator++() { 00305 COMET_ASSERT( cont_!=NULL); 00306 COMET_ASSERT( get_const_raw() < cont_->end().get_raw() ); 00307 ++iter_; 00308 return *this; 00309 } 00310 00311 sa_debug_iterator operator--(int) { 00312 COMET_ASSERT( cont_!=NULL); 00313 COMET_ASSERT( get_const_raw() > cont_->begin().get_raw() ); 00314 sa_debug_iterator t(*this); 00315 --iter_; 00316 return t; 00317 } 00318 00319 sa_debug_iterator& operator--() { 00320 COMET_ASSERT( cont_!=NULL); 00321 COMET_ASSERT( get_const_raw() > cont_->begin().get_raw() ); 00322 --iter_; 00323 return *this; 00324 } 00325 00326 typename TRAITS::reference operator[](size_t n) { 00327 COMET_ASSERT( cont_!=NULL); 00328 COMET_ASSERT( (get_const_raw()+ n) >= cont_->begin().get_raw()); 00329 COMET_ASSERT( (get_cosnt_raw()+n) < cont_->end().get_raw() ); 00330 return iter_[n]; 00331 } 00332 00333 sa_debug_iterator& operator+=(size_t n) { 00334 COMET_ASSERT(cont_!=NULL); 00335 COMET_ASSERT((get_const_raw()+ n) >= cont_->begin().get_raw()); 00336 COMET_ASSERT((get_const_raw()+n) <= cont_->end().get_raw() ); 00337 iter_ += n; 00338 return *this; 00339 } 00340 00341 sa_debug_iterator& operator-=(size_t n) { 00342 COMET_ASSERT( cont_!=NULL); 00343 COMET_ASSERT( (get_const_raw()- n) >= cont_->begin().get_raw()); 00344 COMET_ASSERT( (get_const_raw()- n) <= cont_->end().get_raw() ); 00345 iter_ -= n; 00346 return *this; 00347 } 00348 00349 ptrdiff_t operator-(const sa_debug_iterator& it) const { 00350 COMET_ASSERT( cont_!=NULL); 00351 COMET_ASSERT( cont_ == it.cont_); 00352 return iter_ - it.iter_; 00353 } 00354 00355 bool operator<(const sa_debug_iterator& it) const { 00356 COMET_ASSERT( cont_!=NULL); 00357 COMET_ASSERT( cont_ == it.cont_); 00358 return iter_ < it.iter_; 00359 } 00360 00361 bool operator>(const sa_debug_iterator& it) const { 00362 COMET_ASSERT( cont_!=NULL); 00363 COMET_ASSERT( cont_ == it.cont_); 00364 return iter_ > it.iter_; 00365 } 00366 00367 bool operator<=(const sa_debug_iterator& it) const { 00368 COMET_ASSERT( cont_!=NULL); 00369 COMET_ASSERT( cont_ == it.cont_); 00370 return iter_ <= it.iter_; 00371 } 00372 00373 bool operator>=(const sa_debug_iterator& it) const { 00374 COMET_ASSERT( cont_!=NULL); 00375 COMET_ASSERT( cont_ == it.cont_); 00376 return iter_ >= it.iter_; 00377 } 00378 00379 bool operator==(const sa_debug_iterator& it) const { 00380 COMET_ASSERT( cont_!=NULL); 00381 COMET_ASSERT( cont_ == it.cont_); 00382 return iter_ == it.iter_; 00383 } 00384 00385 bool operator!=(const sa_debug_iterator& it) const { 00386 COMET_ASSERT( cont_!=NULL); 00387 COMET_ASSERT( cont_ == it.cont_); 00388 return iter_ != it.iter_; 00389 } 00390 00391 sa_debug_iterator operator+(size_t n) const { 00392 COMET_ASSERT( cont_!=NULL); 00393 COMET_ASSERT( (get_const_raw() + n) >= cont_->begin().get_raw()); 00394 COMET_ASSERT( (get_const_raw() + n) <= cont_->end().get_raw() ); 00395 return sa_debug_iterator( iter_+n, cont_); 00396 } 00397 00398 sa_debug_iterator operator-(size_t n) const { 00399 COMET_ASSERT( cont_!=NULL); 00400 COMET_ASSERT( (get_const_raw() - n) >= cont_->begin().get_raw()); 00401 COMET_ASSERT( (get_const_raw() - n) <= cont_->end().get_raw() ); 00402 return sa_debug_iterator( iter_-n, cont_); 00403 } 00404 00405 typename TRAITS::reference operator*() { 00406 COMET_ASSERT( cont_ != NULL); 00407 COMET_ASSERT( (get_const_raw()) >= cont_->begin().get_raw()); 00408 COMET_ASSERT( (get_const_raw()) < cont_->end().get_raw() ); 00409 return *iter_; 00410 } 00411 }; 00412 00413 00414 #else // COMET_ITERATOR_DEBUG 00415 #define COMET_IT_DBG__(x) 00416 #define COMET_SAIT_THIS 00417 #define COMET_SAIT_ITER(CONT_, IT_, TRAITS_) IT_ 00418 #endif // COMET_ITERATOR_DEBUG 00419 00420 00423 template<typename T, typename TR> class sa_iterator : public std::iterator<std::random_access_iterator_tag, typename TR::value_type>, 00424 public access_operator<type_traits::is_class_pointer<T>::result>::base< T, sa_iterator<T,TR> > 00425 00426 { 00427 typedef sa_iterator<T, nonconst_traits<T> > nonconst_self; 00428 public: 00429 typedef sa_traits<T> traits; 00430 typename traits::raw* ptr_; 00431 00432 typedef typename TR::pointer pointer; 00433 typedef typename TR::reference reference; 00434 typedef ptrdiff_t difference_type; 00435 00436 sa_iterator(const nonconst_self& it ) 00437 : ptr_(it.get_raw()) 00438 {} 00439 00440 explicit sa_iterator(typename traits::raw* ptr) : ptr_(ptr) {} 00441 00442 sa_iterator() {} 00443 00444 typename traits::raw* get_raw() const 00445 { 00446 return ptr_; 00447 } 00448 00449 sa_iterator operator++(int) { 00450 sa_iterator t(*this); 00451 ++ptr_; 00452 return t; 00453 } 00454 00455 sa_iterator& operator++() { 00456 ++ptr_; 00457 return *this; 00458 } 00459 00460 sa_iterator operator--(int) { 00461 sa_iterator t(*this); 00462 --ptr_; 00463 return t; 00464 } 00465 00466 sa_iterator& operator--() { 00467 --ptr_; 00468 return *this; 00469 } 00470 00471 reference operator[](size_t n) { 00472 return traits::create_reference(ptr_[n]); 00473 } 00474 00475 sa_iterator& operator+=(size_t n) { 00476 ptr_ += n; 00477 return *this; 00478 } 00479 00480 sa_iterator& operator-=(size_t n) { 00481 ptr_ -= n; 00482 return *this; 00483 } 00484 00485 difference_type operator-(const sa_iterator& it) const { 00486 return ptr_ - it.ptr_; 00487 } 00488 00489 bool operator<(const sa_iterator& it) const { 00490 return ptr_ < it.ptr_; 00491 } 00492 00493 bool operator>(const sa_iterator& it) const { 00494 return ptr_ > it.ptr_; 00495 } 00496 00497 bool operator<=(const sa_iterator& it) const { 00498 return ptr_ <= it.ptr_; 00499 } 00500 00501 bool operator>=(const sa_iterator& it) const { 00502 return ptr_ >= it.ptr_; 00503 } 00504 00505 bool operator==(const sa_iterator& it) const { 00506 return ptr_ == it.ptr_; 00507 } 00508 00509 bool operator!=(const sa_iterator& it) const { 00510 return ptr_ != it.ptr_; 00511 } 00512 00513 sa_iterator operator+(size_t n) const { 00514 return sa_iterator(ptr_ + n); 00515 } 00516 00517 sa_iterator operator-(size_t n) const { 00518 return sa_iterator(ptr_ - n); 00519 } 00520 00521 template<typename T2, typename TR2> friend sa_iterator<T2, TR2> operator+(size_t n, const sa_iterator<T2, TR2>& it); 00522 // friend sa_iterator operator+(size_t n, const sa_iterator&); 00523 00524 reference operator*() { return traits::create_reference(*ptr_); } 00525 }; 00526 00527 } 00528 00529 namespace impl 00530 { 00531 template <typename T> 00532 class safearray_auto_ref_t; 00533 00534 template <typename T> 00535 class safearray_auto_const_ref_t; 00536 }; 00537 00544 template<typename T> class safearray_t 00545 { 00546 public: 00547 typedef impl::sa_traits<T> traits; 00548 typedef size_t size_type; 00549 typedef long index_type; 00550 typedef ptrdiff_t difference_type; 00551 typedef typename traits::value_type value_type; 00552 typedef typename traits::reference reference; 00553 typedef typename traits::const_reference const_reference; 00554 00555 typedef typename COMET_SAIT_ITER( safearray_t, traits::iterator, impl::sa_debug_traits<traits> ) 00556 iterator; 00557 typedef typename COMET_SAIT_ITER( safearray_t, traits::const_iterator, impl::sa_const_debug_traits<traits>) 00558 const_iterator; 00559 00560 #if defined(COMET_STD_ITERATOR) 00561 typedef std::reverse_iterator<iterator> reverse_iterator; 00562 typedef std::reverse_iterator<const_iterator> const_reverse_iterator; 00563 #else 00564 // workaround for broken reverse_iterator implementations due to no partial specialisation 00565 typedef std::reverse_iterator<iterator,T> reverse_iterator; 00566 typedef std::reverse_iterator<const_iterator,T> const_reverse_iterator; 00567 #endif 00568 00570 00571 iterator begin() { 00572 return iterator(get_array() COMET_SAIT_THIS ); 00573 } 00574 00575 iterator end() { 00576 return iterator(get_array() + size() COMET_SAIT_THIS ); 00577 } 00578 00579 const_iterator begin() const { 00580 return const_iterator(get_array() COMET_SAIT_THIS) ; 00581 } 00582 00583 const_iterator end() const { 00584 return const_iterator(get_array() + size() COMET_SAIT_THIS ); 00585 } 00586 00587 reverse_iterator rbegin() { 00588 return reverse_iterator(end()); 00589 } 00590 00591 reverse_iterator rend() { 00592 return reverse_iterator(begin()); 00593 } 00594 00595 const_reverse_iterator rbegin() const { 00596 return const_reverse_iterator(end()); 00597 } 00598 00599 const_reverse_iterator rend() const { 00600 return const_reverse_iterator(begin()); 00601 } 00603 00605 size_type size() const { 00606 return psa_ ? psa_->rgsabound[0].cElements : 0; 00607 } 00608 00610 bool is_empty() const { 00611 return size() == 0; 00612 } 00613 00615 reference operator[](index_type n) { 00616 COMET_ASSERT( (size_type)(n - lower_bound()) < size() ); 00617 return traits::create_reference(get_element(n)); 00618 } 00619 00621 const_reference operator[](index_type n) const { 00622 COMET_ASSERT( (size_type)(n - lower_bound()) < size() ); 00623 return traits::create_reference(get_element(n)); 00624 } 00625 00627 00629 reference at(index_type n) { 00630 range_check(n); 00631 return traits::create_reference(get_element(n)); 00632 } 00633 00635 00637 const_reference at(index_type n) const { 00638 range_check(n); 00639 return traits::create_reference(get_element(n)); 00640 } 00641 00643 reference front() { return *begin(); } 00645 const_reference front() const { return *begin(); } 00647 reference back() { return *(end() - 1); } 00649 const_reference back() const { return *(end() - 1); } 00650 00651 private: 00652 template<enum impl::sa_traits_extras_type STET> 00653 struct get_extras 00654 { 00655 static void *extras(){ return 0; } 00656 }; 00657 template<> 00658 struct get_extras<impl::stet_record> 00659 { 00660 static void *extras(){ return impl::sa_traits<T>::get_record_info().in(); } 00661 }; 00662 template<> 00663 struct get_extras<impl::stet_iid> 00664 { 00665 static void *extras(){ return impl::sa_traits<T>::iid().in_ptr(); } 00666 }; 00667 00668 public: 00669 00671 00672 00673 safearray_t() : psa_(0) 00674 {} 00675 00682 safearray_t(const impl::auto_attach_t<SAFEARRAY*>& psa) : psa_(psa.get()) 00683 { 00684 sanity_check(psa_); 00685 00686 if (psa_) try { 00687 ::SafeArrayLock(psa_) | raise_exception; 00688 } catch (...) 00689 { 00690 ::SafeArrayDestroy(psa_); 00691 throw; 00692 } 00693 } 00694 00696 safearray_t(const variant_t& var) 00697 { 00698 if(var.get_vt() == (VT_ARRAY|traits::vt)) 00699 { 00700 SafeArrayCopy(var.in().parray, &psa_) | raise_exception; 00701 } else { 00702 variant_t v2(var, VT_ARRAY|traits::vt); 00703 SafeArrayCopy(v2.in().parray, &psa_) | raise_exception; 00704 } 00705 00706 if (psa_) try { 00707 ::SafeArrayLock(psa_) | raise_exception; 00708 } catch (...) 00709 { 00710 ::SafeArrayDestroy(psa_); 00711 throw; 00712 } 00713 00714 } 00715 00717 safearray_t(const safearray_t& sa) 00718 { 00719 ::SafeArrayCopy(sa.psa_, &psa_) | raise_exception; 00720 00721 if (psa_) try { 00722 ::SafeArrayLock(psa_) | raise_exception; 00723 } catch (...) 00724 { 00725 ::SafeArrayDestroy(psa_); 00726 throw; 00727 } 00728 } 00729 00731 00734 explicit safearray_t(size_type sz, index_type lb) 00735 { 00736 psa_ = ::SafeArrayCreateVectorEx(traits::vt, lb, sz, get_extras<impl::sa_traits_extras_type(traits::extras_type)>::extras()); 00737 if (psa_ == 0) throw std::bad_alloc(); 00738 00739 try { 00740 ::SafeArrayLock(psa_) | raise_exception; 00741 } catch (...) 00742 { 00743 ::SafeArrayDestroy(psa_); 00744 throw; 00745 } 00746 } 00747 00749 00753 safearray_t(size_type sz, index_type lb, const T& val) 00754 { 00755 psa_ = ::SafeArrayCreateVectorEx(traits::vt, lb, sz, get_extras<impl::sa_traits_extras_type(traits::extras_type)>::extras()); 00756 if (psa_ == 0) throw std::bad_alloc(); 00757 00758 try { 00759 ::SafeArrayLock(psa_) | raise_exception; 00760 00761 for (iterator it = begin(); it != end(); ++it) *it = val; 00762 } catch (...) { 00763 ::SafeArrayUnlock(psa_); 00764 ::SafeArrayDestroy(psa_); 00765 throw; 00766 } 00767 } 00768 00770 00774 template<typename InputIterator> safearray_t(InputIterator first, InputIterator last, index_type lb) 00775 { 00776 initialise_aux(first, last, lb, type_traits::int_holder< type_traits::is_integer<InputIterator>::result >()); 00777 } 00779 00780 private: 00781 template<typename InputIterator> void initialise_aux(InputIterator first, InputIterator last, index_type lb, type_traits::int_holder<false>) 00782 { 00783 size_type sz = std::distance(first, last); 00784 00785 psa_ = ::SafeArrayCreateVectorEx(traits::vt, lb, sz,get_extras<impl::sa_traits_extras_type(traits::extras_type)>::extras()); 00786 if (psa_ == 0) throw std::bad_alloc(); 00787 00788 try { 00789 ::SafeArrayLock(psa_) | raise_exception; 00790 00791 for (iterator it = begin(); first != last; ++first, ++it) { 00792 *it = *first; 00793 } 00794 } catch (...) { 00795 ::SafeArrayUnlock(psa_); 00796 ::SafeArrayDestroy(psa_); 00797 throw; 00798 } 00799 } 00800 00801 template<typename Integer> void initialise_aux(Integer sz, Integer lb, index_type dummy, type_traits::int_holder<true>) 00802 { 00803 psa_ = ::SafeArrayCreateVectorEx(traits::vt, lb, sz,get_extras<impl::sa_traits_extras_type(traits::extras_type)>::extras()); 00804 if (psa_ == 0) throw std::bad_alloc(); 00805 00806 ::SafeArrayLock(psa_) | raise_exception; 00807 } 00808 00809 public: 00811 00813 void resize(size_type n) 00814 { 00815 resize_bound(n, (psa_==NULL)?0:lower_bound()); 00816 } 00818 // This has been renamed to prevent ambiguous functions when T = size_type 00819 void resize_bound(size_type n, size_type lb) 00820 { 00821 safearray_t t(n, lb); 00822 00823 iterator i1 = begin(); 00824 iterator i2 = t.begin(); 00825 00826 for (;i1 != end() && i2 != t.end(); ++i1, ++i2) { 00827 std::swap(*i1, *i2); 00828 } 00829 00830 swap(t); 00831 } 00832 00836 void resize( size_type n, const T& val) { 00837 resize_bound(n,(psa_==NULL)?0:lower_bound(),val); 00838 } 00842 void resize_bound(size_type n, size_type lb, const T& val) { 00843 safearray_t t(n, lb); 00844 00845 iterator i1 = begin(); 00846 iterator i2 = t.begin(); 00847 00848 for (;i1 != end() && i2 != t.end(); ++i1, ++i2) { 00849 std::swap(*i1, *i2); 00850 } 00851 00852 for (;i2 != t.end(); ++i2) *i2 = val; 00853 00854 swap(t); 00855 } 00856 00858 void assign(size_type n, const T& val) { 00859 safearray_t t(n, lower_bound(), val); 00860 swap(t); 00861 } 00862 00864 template<typename InputIterator> void assign(InputIterator first, InputIterator last) { 00865 assign_aux(first, last, type_traits::int_holder< type_traits::is_integer<InputIterator>::result >()); 00866 } 00867 00870 com_ptr<IRecordInfo> get_record_info() 00871 { 00872 com_ptr<IRecordInfo> rec_info; 00873 ::SafeArrayGetRecordInfo(psa_, rec_info.out()) | raise_exception; 00874 return rec_info; 00875 } 00878 VARTYPE get_vt() 00879 { 00880 // Something appears broken in SafeArrayGetVartype - returning VT_UNKNOWN when it has FADF_DISPATCH set. 00881 if (psa_->fFeatures & FADF_DISPATCH) return VT_DISPATCH; 00882 if (psa_->fFeatures & FADF_UNKNOWN) return VT_UNKNOWN; 00883 VARTYPE retval; 00884 ::SafeArrayGetVartype(psa_, &retval) | raise_exception; 00885 return retval; 00886 } 00887 00890 uuid_t get_iid() 00891 { 00892 uuid_t iid; 00893 ::SafeArrayGetIID(psa_, &iid) | raise_exception; 00894 return iid; 00895 } 00896 00897 private: 00898 template<typename InputIterator> void assign_aux(InputIterator first, InputIterator last, type_traits::int_holder<false>) 00899 { 00900 safearray_t t( first, last, lower_bound() ); 00901 swap(t); 00902 } 00903 00904 template<typename Integer> void assign_aux(Integer sz, const T& val, type_traits::int_holder<true>) 00905 { 00906 safearray_t t(sz, lower_bound(), val); 00907 swap(t); 00908 } 00909 public: 00910 00912 void insert(iterator pos, size_type n, const T& val) { 00913 safearray_t t(n+size(), lower_bound()); 00914 iterator i1 = t.begin(); 00915 iterator i2 = begin(); 00916 00917 for (;i2 != pos; ++i1, ++i2) *i1 = *i2; 00918 for (;n>0;--n, ++i1) *i1 = val; 00919 for (;i2 != end(); ++i1, ++i2) *i1 = *i2; 00920 00921 swap(t); 00922 } 00923 00924 00926 template<typename InputIterator> void insert(iterator pos, InputIterator first, InputIterator last) { 00927 insert_aux(pos, first, last, type_traits::int_holder<type_traits::is_integer<InputIterator>::result >()); 00928 } 00929 00931 void push_back( const T& val, index_type lb ) 00932 { 00933 safearray_t t(size()+1, lb); 00934 00935 iterator i1 = begin(), i2 = t.begin(); 00936 00937 for (;i1 != end() ; ++i1, ++i2) 00938 std::swap(*i1, *i2); 00939 00940 *i2 = val; 00941 00942 swap(t); 00943 } 00944 00946 inline void push_back( const T& val) 00947 { 00948 push_back(val, lower_bound()); 00949 } 00950 00952 inline void pop_back() 00953 { 00954 size_type lastone = size(); 00955 if (lastone > 0) 00956 erase(begin()+(lastone-1)); 00957 } 00958 00960 void push_front( const T &val, index_type lb) 00961 { 00962 safearray_t t(size()+1, lb); 00963 00964 iterator i1 = begin(), i2 = t.begin(); 00965 00966 *i2 = val; 00967 00968 for (++i2; i1 != end(); ++i1, ++i2) 00969 std::swap(*i1, *i2); 00970 00971 swap(t); 00972 } 00974 inline void push_front( const T &val) 00975 { 00976 push_front(val, lower_bound()); 00977 } 00979 inline void pop_front() 00980 { 00981 erase(begin()); 00982 } 00983 00985 00988 iterator erase(iterator it) 00989 { 00990 if (it == end()) 00991 return end(); 00992 size_type where= it-begin(); 00993 00994 safearray_t t(size()-1, lower_bound()); 00995 iterator ret = t.end(); 00996 iterator i1 = begin(), i2 = t.begin(); 00997 // Copy up to iterator 00998 for (; i1 != end() && i1 != it; ++i1, ++i2) 00999 std::swap(*i1,*i2); 01000 ++i1;// Skip this one 01001 for (; i1 != end(); ++i1, ++i2) 01002 std::swap(*i1,*i2); 01003 01004 swap(t); 01005 return begin()+where; 01006 } 01007 01009 01013 iterator erase(iterator first, iterator second) 01014 { 01015 safearray_t t(size()-(second-first), lower_bound()); 01016 size_type where= first-begin(); 01017 iterator i1 = begin(), i2 = t.begin(); 01018 // Copy up to first. 01019 for (; i1 != end() && i1 != first; ++i1, ++i2) 01020 std::swap(*i1,*i2); 01021 // Skip up to second 01022 for( ; i1 != second; ++i1) 01023 ; 01024 // skip to end. 01025 for (; i1 != end(); ++i1, ++i2) 01026 std::swap(*i1,*i2); 01027 01028 swap(t); 01029 return begin()+where; 01030 } 01031 01032 01033 private: 01034 template<typename InputIterator> void insert_aux(iterator pos, InputIterator first, InputIterator last, type_traits::int_holder<false>) { 01035 size_type n = std::distance(first, last); 01036 01037 safearray_t t(n+size(), lower_bound()); 01038 iterator i1 = t.begin(); 01039 iterator i2 = begin(); 01040 01041 for (;i2 != pos; ++i1, ++i2) *i1 = *i2; 01042 for (;first != last; ++i1, ++first) *i1 = *first; 01043 for (;i2 != end(); ++i1, ++i2) *i1 = *i2; 01044 01045 swap(t); 01046 } 01047 01048 template<typename Integer> void insert_aux(iterator pos, Integer n, const T& val, type_traits::int_holder<true>) { 01049 safearray_t t(n+size(), lower_bound()); 01050 iterator i1 = t.begin(); 01051 iterator i2 = begin(); 01052 01053 for (;i2 != pos; ++i1, ++i2) *i1 = *i2; 01054 for (;n>0;--n, ++i1) *i1 = val; 01055 for (;i2 != end(); ++i1, ++i2) *i1 = *i2; 01056 01057 swap(t); 01058 } 01059 public: 01060 01062 01063 safearray_t& operator=(const safearray_t& sa) 01064 { 01065 safearray_t t(sa); 01066 swap(t); 01067 return *this; 01068 } 01069 01070 safearray_t& operator=(const variant_t& v) 01071 { 01072 safearray_t t(v); 01073 swap(t); 01074 return *this; 01075 } 01076 01077 safearray_t& operator=(const impl::auto_attach_t<SAFEARRAY*>& sa) 01078 { 01079 safearray_t t(sa); 01080 swap(t); 01081 return *this; 01082 } 01084 01085 private: 01086 void destroy() { 01087 if (psa_ != 0) { 01088 COMET_ASSERT(psa_->cLocks == 1); 01089 ::SafeArrayUnlock(psa_); 01090 ::SafeArrayDestroy(psa_); 01091 psa_ = 0; 01092 } 01093 } 01094 01095 public: 01096 01097 ~safearray_t() { 01098 destroy(); 01099 } 01100 01102 SAFEARRAY* detach() { 01103 if (psa_) { 01104 ::SafeArrayUnlock(psa_); 01105 } 01106 SAFEARRAY* rv = psa_; 01107 psa_ = 0; 01108 return rv; 01109 } 01110 01119 void detach_to( variant_t &var) 01120 { 01121 COMET_ASSERT(psa_->cLocks == 1); 01122 if (psa_) ::SafeArrayUnlock(psa_) | raise_exception; 01123 var = auto_attach( psa_ ); 01124 psa_= 0; 01125 } 01126 01130 void detach_from( variant_t &var) 01131 { 01132 if(var.get_vt()!=(VT_ARRAY|traits::vt)) 01133 { 01134 var.change_type(VT_ARRAY|traits::vt); 01135 } 01136 safearray_t t(auto_attach(var.detach().parray)); 01137 swap(t); 01138 } 01139 01141 01143 index_type lower_bound() const { 01144 return psa_ ? psa_->rgsabound[0].lLbound : 0; 01145 } 01146 01148 void lower_bound(index_type lb) { 01149 psa_->rgsabound[0].lLbound = lb; 01150 } 01151 01152 private: 01153 class sa_auto_lock_t 01154 { 01155 SAFEARRAY** ppsa_; 01156 01157 // These are not available 01158 sa_auto_lock_t(); 01159 sa_auto_lock_t(const sa_auto_lock_t&); 01160 sa_auto_lock_t& operator=(const sa_auto_lock_t&); 01161 public: 01162 operator SAFEARRAY**() throw() { return ppsa_; } 01163 01164 sa_auto_lock_t(SAFEARRAY** ppsa) : ppsa_(ppsa) {} 01165 01166 ~sa_auto_lock_t() 01167 { 01168 if (*ppsa_) { 01169 HRESULT hr = ::SafeArrayLock(*ppsa_); 01170 COMET_ASSERT( SUCCEEDED(hr) ); 01171 hr; 01172 } 01173 } 01174 }; 01175 01176 public: 01178 01179 SAFEARRAY* in() const throw() { 01180 return const_cast<SAFEARRAY*>(psa_); 01181 } 01182 SAFEARRAY** in_ptr() const throw() { 01183 return const_cast<SAFEARRAY**>(&psa_); 01184 } 01185 sa_auto_lock_t inout() throw() { 01186 if (psa_) { 01187 ::SafeArrayUnlock(psa_); 01188 } 01189 return &psa_; 01190 } 01191 sa_auto_lock_t out() throw() { 01192 destroy(); 01193 return &psa_; 01194 } 01196 01198 static SAFEARRAY* detach(safearray_t& sa) 01199 { 01200 return sa.detach(); 01201 } 01202 01206 static const impl::safearray_auto_const_ref_t<T> create_const_reference(SAFEARRAY* const & sa); 01207 static impl::safearray_auto_ref_t<T> create_reference(SAFEARRAY* & sa); 01208 01217 static const impl::safearray_auto_const_ref_t<T> create_const_reference(const variant_t &var); 01220 static impl::safearray_auto_ref_t<T> create_reference(variant_t &var); 01221 01222 void swap(safearray_t& sa) throw() 01223 { 01224 std::swap(psa_, sa.psa_); 01225 } 01226 01227 private: 01228 01229 void range_check(index_type n) const { 01230 size_type m = (size_type)(n - lower_bound()); 01231 if (/*m < 0 || */ m >= size()) throw std::out_of_range("safearray_t"); 01232 } 01233 01234 typename traits::raw* get_array() const { 01235 if (psa_) { 01236 COMET_ASSERT(psa_->cLocks != 0); 01237 return static_cast<typename traits::raw*>(psa_->pvData); 01238 } 01239 return NULL; 01240 } 01241 01242 typename traits::raw& get_element(size_type n) const { 01243 return get_array()[n - lower_bound()]; 01244 } 01245 01246 protected: 01247 SAFEARRAY* psa_; 01248 01249 template< enum impl::sa_traits_check_type STCT > 01250 struct traits_sanity_check 01251 { static inline void check( const SAFEARRAY *psa) { } }; 01252 template<> 01253 struct traits_sanity_check<impl::stct_vt_ok> 01254 { 01255 static void check(SAFEARRAY *psa) { 01256 if ((psa->fFeatures & FADF_HAVEVARTYPE)!=0) 01257 { 01258 VARTYPE vt; 01259 ::SafeArrayGetVartype(psa, &vt) | raise_exception ; 01260 if(vt != impl::sa_traits<T>::vt) 01261 throw std::runtime_error("safearray_t: VarType mismatch"); 01262 } 01263 } 01264 }; 01265 template<> 01266 struct traits_sanity_check<impl::stct_iid_ok> { 01267 static void check(SAFEARRAY *psa) 01268 { 01269 uuid_t iid; 01270 ::SafeArrayGetIID(psa, &iid) | raise_exception; 01271 if( iid != impl::sa_traits<T>::iid() ) 01272 throw std::runtime_error("safearray_t: IID mismatch"); 01273 } 01274 }; 01275 01277 static void sanity_check(SAFEARRAY* psa) { 01278 if (psa == 0) return; 01279 if (psa->cDims != 1) throw std::runtime_error("safearray_t: Invalid dimension"); 01280 if (!traits::are_features_ok( psa->fFeatures )) throw std::runtime_error("safearray_t: fFeatures is invalid"); 01281 traits_sanity_check< impl::sa_traits_check_type(traits::check_type)>::check(psa); 01282 if (sizeof(T) != psa->cbElements) throw std::runtime_error("safearray_t: cbElements mismatch"); 01283 } 01284 01285 }; 01287 01288 namespace impl { 01289 01290 template< typename T> 01291 class safearray_auto_ref_t : public safearray_t<T> 01292 { 01293 // Don't allow any of these. 01294 safearray_auto_ref_t(); 01295 safearray_auto_ref_t &operator=(const safearray_auto_ref_t &); 01296 safearray_auto_ref_t &operator=(const safearray_t<T> &); 01297 safearray_t<T>& operator=(const impl::auto_attach_t<SAFEARRAY*> &); 01298 void swap(safearray_t<T>& sa); 01299 01300 // Remember where we got the original for a non-const reference 01301 SAFEARRAY *& psa_; 01302 01303 public: 01304 safearray_auto_ref_t(const safearray_auto_ref_t &sa) 01305 : safearray_t<T>(auto_attach(sa.psa_)), psa_(sa.psa_) 01306 { 01307 COMET_STATIC_ASSERT(false); 01308 } 01309 01310 explicit safearray_auto_ref_t(SAFEARRAY *& psa) 01311 : safearray_t<T>(auto_attach(psa)), psa_(psa) 01312 { 01313 } 01314 01315 ~safearray_auto_ref_t() 01316 { 01317 psa_ = detach(); 01318 } 01319 }; 01320 01321 template< typename T> 01322 class safearray_auto_const_ref_t : public safearray_t<T> 01323 { 01324 // Don't allow any of these. 01325 safearray_auto_const_ref_t(); 01326 safearray_auto_const_ref_t &operator=(const safearray_auto_const_ref_t &); 01327 safearray_auto_const_ref_t &operator=(const safearray_t<T> &); 01328 safearray_t<T>& operator=(const impl::auto_attach_t<SAFEARRAY*> &); 01329 void swap(safearray_t<T>& sa); 01330 01331 public: 01332 safearray_auto_const_ref_t(const safearray_auto_const_ref_t &sa) 01333 : safearray_t<T>(auto_attach(sa.psa_)) 01334 { 01335 COMET_STATIC_ASSERT(false); 01336 } 01337 01338 explicit safearray_auto_const_ref_t(SAFEARRAY *psa) 01339 : safearray_t<T>(auto_attach(psa)) 01340 { 01341 } 01342 01343 ~safearray_auto_const_ref_t() 01344 { 01345 detach(); 01346 } 01347 }; 01348 01349 } 01350 01351 template<typename T> 01352 const impl::safearray_auto_const_ref_t<T> safearray_t<T>::create_const_reference(SAFEARRAY* const & sa) 01353 { 01354 return impl::safearray_auto_const_ref_t<T>(sa); 01355 } 01356 template<typename T> 01357 impl::safearray_auto_ref_t<T> safearray_t<T>::create_reference(SAFEARRAY* & sa) 01358 { 01359 return impl::safearray_auto_ref_t<T>(sa); 01360 } 01361 template<typename T> 01362 const impl::safearray_auto_const_ref_t<T> safearray_t<T>::create_const_reference(const variant_t &var) 01363 { 01364 if(var.get_vt()!=(VT_ARRAY|traits::vt)) 01365 throw std::exception("unexepected array type"); 01366 01367 SAFEARRAY *sa = var.get().parray; 01368 return impl::safearray_auto_const_ref_t<T>(sa); 01369 } 01370 template<typename T> 01371 impl::safearray_auto_ref_t<T> safearray_t<T>::create_reference(variant_t &var) 01372 { 01373 if(var.get_vt()!=(VT_ARRAY|traits::vt)) 01374 throw std::exception("unexepected array type"); 01375 01376 SAFEARRAY *sa = var.get().parray; 01377 return impl::safearray_auto_ref_t<T>(sa); 01378 } 01379 01380 01381 01382 template<typename T, typename TR> inline comet::impl::sa_iterator<T, TR> operator+(size_t n, const comet::impl::sa_iterator<T, TR>& it) { 01383 return it + n; 01384 } 01385 01386 } // namespace comet 01387 01388 namespace { 01389 COMET_STATIC_ASSERT( sizeof(SAFEARRAY*) == sizeof(comet::safearray_t<long>) ); 01390 } 01391 01392 namespace std { 01393 template<> inline void swap( comet::safearray_t<long>& x, comet::safearray_t<long>& y) COMET_STD_SWAP_NOTHROW; 01394 template<> inline void swap( comet::safearray_t<unsigned long>& x, comet::safearray_t<unsigned long>& y) COMET_STD_SWAP_NOTHROW; 01395 template<> inline void swap( comet::safearray_t<short>& x, comet::safearray_t<short>& y) COMET_STD_SWAP_NOTHROW; 01396 template<> inline void swap( comet::safearray_t<unsigned short>& x, comet::safearray_t<unsigned short>& y) COMET_STD_SWAP_NOTHROW; 01397 template<> inline void swap( comet::safearray_t<float>& x, comet::safearray_t<float>& y) COMET_STD_SWAP_NOTHROW; 01398 template<> inline void swap( comet::safearray_t<double>& x, comet::safearray_t<double>& y) COMET_STD_SWAP_NOTHROW; 01399 template<> inline void swap( comet::safearray_t<comet::bstr_t>& x, comet::safearray_t<comet::bstr_t>& y) COMET_STD_SWAP_NOTHROW; 01400 template<> inline void swap( comet::safearray_t<comet::variant_t>& x, comet::safearray_t<comet::variant_t>& y) COMET_STD_SWAP_NOTHROW; 01401 template<> inline void swap( comet::safearray_t<comet::com_ptr< ::IUnknown> >& x, comet::safearray_t<comet::com_ptr< ::IUnknown> >& y) COMET_STD_SWAP_NOTHROW; 01402 template<> inline void swap( comet::safearray_t<comet::com_ptr< ::IDispatch> >& x, comet::safearray_t<comet::com_ptr< ::IDispatch> >& y) COMET_STD_SWAP_NOTHROW; 01403 } 01404 01405 template<> inline void std::swap( comet::safearray_t<long>& x, comet::safearray_t<long>& y) COMET_STD_SWAP_NOTHROW { x.swap(y); } 01406 template<> inline void std::swap( comet::safearray_t<unsigned long>& x, comet::safearray_t<unsigned long>& y) COMET_STD_SWAP_NOTHROW { x.swap(y); } 01407 template<> inline void std::swap( comet::safearray_t<short>& x, comet::safearray_t<short>& y) COMET_STD_SWAP_NOTHROW { x.swap(y); } 01408 template<> inline void std::swap( comet::safearray_t<unsigned short>& x, comet::safearray_t<unsigned short>& y) COMET_STD_SWAP_NOTHROW { x.swap(y); } 01409 template<> inline void std::swap( comet::safearray_t<float>& x, comet::safearray_t<float>& y) COMET_STD_SWAP_NOTHROW { x.swap(y); } 01410 template<> inline void std::swap( comet::safearray_t<double>& x, comet::safearray_t<double>& y) COMET_STD_SWAP_NOTHROW { x.swap(y); } 01411 template<> inline void std::swap( comet::safearray_t<comet::bstr_t>& x, comet::safearray_t<comet::bstr_t>& y) COMET_STD_SWAP_NOTHROW { x.swap(y); } 01412 template<> inline void std::swap( comet::safearray_t<comet::variant_t>& x, comet::safearray_t<comet::variant_t>& y) COMET_STD_SWAP_NOTHROW { x.swap(y); } 01413 template<> inline void std::swap( comet::safearray_t<comet::com_ptr< ::IUnknown> >& x, comet::safearray_t<comet::com_ptr< ::IUnknown> >& y) COMET_STD_SWAP_NOTHROW { x.swap(y); } 01414 template<> inline void std::swap( comet::safearray_t<comet::com_ptr< ::IDispatch> >& x, comet::safearray_t<comet::com_ptr< ::IDispatch> >& y) COMET_STD_SWAP_NOTHROW { x.swap(y); } 01415 01416 #endif