00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069 #ifndef COMSTL_INCL_H_COMSTL
00070 # include "comstl.h"
00071 #endif
00072
00073 #if defined(__STLSOFT_COMPILER_IS_MSVC) && \
00074 _MSC_VER < 1200
00075 # error comstl_interface_cast.h is not compatible with Visual C++ 5.0 or earlier
00076 #endif
00077
00078 #ifndef COMSTL_INCL_H_COMSTL_REFCOUNT_FUNCTIONS
00079 # include "comstl_refcount_functions.h"
00080 #endif
00081 #ifndef COMSTL_INCL_H_COMSTL_INTERFACE_TRAITS
00082 # include "comstl_interface_traits.h"
00083 #endif
00084 #ifndef COMSTL_INCL_H_COMSTL_BAD_INTERFACE_CAST
00085 # include "comstl_bad_interface_cast.h"
00086 #endif
00087 #ifndef STLSOFT_INCL_H_STLSOFT_OPERATOR_BOOL
00088 # include "stlsoft_operator_bool.h"
00089 #endif
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108 #ifndef _COMSTL_NO_NAMESPACE
00109 # if defined(_STLSOFT_NO_NAMESPACE) || \
00110 defined(__STLSOFT_DOCUMENTATION_SKIP_SECTION)
00111
00112 namespace comstl
00113 {
00114 # else
00115
00116
00117 namespace stlsoft
00118 {
00119
00120 namespace comstl_project
00121 {
00122
00123 # endif
00124 #endif
00125
00126
00127
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141 template <ss_typename_param_k I>
00142 inline I *simple_interface_cast(I *pi)
00143 {
00144 return pi;
00145 }
00146
00147
00148
00149
00150
00152 struct ignore_interface_cast_exception
00153 {
00154 public:
00156 struct thrown_type
00157 {
00158 };
00159
00160 public:
00165 void operator ()(HRESULT hr, REFIID riid) comstl_throw_0()
00166 {
00167 STLSOFT_SUPPRESS_UNUSED(hr);
00168 STLSOFT_SUPPRESS_UNUSED(riid);
00169
00170
00171 }
00172 };
00173
00175 struct throw_bad_interface_cast_exception
00176 {
00177 public:
00179 typedef bad_interface_cast thrown_type;
00180
00181 public:
00186 void operator ()(HRESULT hr, REFIID riid) comstl_throw_1(bad_interface_cast)
00187 {
00188 throw bad_interface_cast(riid, hr);
00189 }
00190 };
00191
00193 template <ss_typename_param_k I>
00194 struct noaddref_release
00195 {
00196 public:
00200 void operator ()(I pi)
00201 {
00202 release(pi);
00203 }
00204 };
00205
00207 template <ss_typename_param_k I>
00208 struct addref_release
00209 {
00210 public:
00214 void operator ()(I pi)
00215 {
00216 STLSOFT_SUPPRESS_UNUSED(pi);
00217 }
00218 };
00219
00220
00221
00222
00223
00224
00225
00226
00227 #ifdef __STLSOFT_CF_TEMPLATE_PARTIAL_SPECIALISATION_SUPPORT
00228
00232 template <ss_typename_param_k I>
00233 struct interface_pointer_traits;
00234
00236 template <ss_typename_param_k I>
00237 struct interface_pointer_traits<I*>
00238 {
00239 typedef I interface_type;
00240 };
00241
00243 template <ss_typename_param_k I>
00244 interface protect_refcount
00245 : public I
00246 {
00247 private:
00248 STDMETHOD_(ULONG, AddRef)()
00249 {
00250 I *pi = static_cast<I*>(this);
00251
00252 return pi->AddRef();
00253 }
00254 STDMETHOD_(ULONG, Release)()
00255 {
00256 I *pi = static_cast<I*>(this);
00257
00258 return pi->Release();
00259 }
00260 };
00261
00262 #endif
00263
00264
00265
00266
00267
00275 template< ss_typename_param_k I
00276 , ss_typename_param_k R
00277 , ss_typename_param_k X
00278 >
00279 class interface_cast_base
00280 {
00281 public:
00283 typedef I interface_pointer_type;
00284 #ifdef __STLSOFT_CF_TEMPLATE_PARTIAL_SPECIALISATION_SUPPORT
00285
00286 typedef ss_typename_type_k interface_pointer_traits<I>::interface_type interface_type;
00287 #endif
00288
00289 typedef R release_type;
00291 typedef X exception_policy_type;
00293 typedef ss_typename_type_k exception_policy_type::thrown_type thrown_type;
00295 typedef interface_cast_base<I, R, X> class_type;
00296
00297
00298 protected:
00300 #ifdef __STLSOFT_CF_MEMBER_TEMPLATE_CTOR_SUPPORT
00301 template <ss_typename_param_k J>
00302 ss_explicit_k interface_cast_base(J &j)
00303 : m_pi(do_cast(simple_interface_cast(j)))
00304 {}
00305 #else
00306 ss_explicit_k interface_cast_base(LPUNKNOWN punk)
00307 : m_pi(do_cast(punk))
00308 {}
00309 #endif
00310
00312 ss_explicit_k interface_cast_base(interface_pointer_type pi)
00313 : m_pi(pi)
00314 {
00315 addref(m_pi);
00316 }
00317
00318 protected:
00320 ~interface_cast_base() comstl_throw_0()
00321 {
00322 if(NULL != m_pi)
00323 {
00324 release_type()(m_pi);
00325 }
00326 }
00327
00328
00329 protected:
00335 static interface_pointer_type do_cast(LPUNKNOWN punk) comstl_throw_1(thrown_type)
00336 {
00337 interface_pointer_type pi;
00338
00339 if(NULL == punk)
00340 {
00341 pi = NULL;
00342 }
00343 else
00344 {
00345 REFIID iid = IID_traits<interface_pointer_type>().iid();
00346 HRESULT hr = punk->QueryInterface(iid, reinterpret_cast<void**>(&pi));
00347
00348 if(FAILED(hr))
00349 {
00350 exception_policy_type()(hr, iid);
00351
00352 pi = NULL;
00353 }
00354 }
00355
00356 return pi;
00357 }
00358
00360 interface_pointer_type const &get_pointer_()
00361 {
00362 return m_pi;
00363 }
00364
00366 interface_pointer_type get_pointer_() const
00367 {
00368 return m_pi;
00369 }
00370
00371
00372 private:
00373 interface_pointer_type const m_pi;
00374
00375
00376 public:
00377 interface_cast_base(class_type const &rhs);
00378 class_type const &operator =(class_type const &rhs);
00379 };
00380
00381
00388 template< ss_typename_param_k I
00389 , ss_typename_param_k X = throw_bad_interface_cast_exception
00390 >
00391 class interface_cast_noaddref
00392 : protected interface_cast_base<I, noaddref_release<I>, X>
00393 {
00394 private:
00395 typedef interface_cast_base<I, noaddref_release<I>, X> parent_class_type;
00396 public:
00398 typedef interface_cast_noaddref<I, X> class_type;
00400 typedef ss_typename_type_k parent_class_type::interface_pointer_type interface_pointer_type;
00401 #ifdef __STLSOFT_CF_TEMPLATE_PARTIAL_SPECIALISATION_SUPPORT
00402
00403 typedef ss_typename_type_k parent_class_type::interface_type interface_type;
00404 typedef protect_refcount<interface_type> *protected_interface_pointer_type;
00405 #else
00406 typedef interface_pointer_type protected_interface_pointer_type;
00407 #endif // __STLSOFT_CF_TEMPLATE_PARTIAL_SPECIALISATION_SUPPORT
00408
00409
00410 public:
00412 #ifdef __STLSOFT_CF_MEMBER_TEMPLATE_CTOR_SUPPORT
00413 template <ss_typename_param_k J>
00414 ss_explicit_k interface_cast_noaddref(J &j)
00415 : parent_class_type(j)
00416 {}
00417 #else
00418 ss_explicit_k interface_cast_noaddref(LPUNKNOWN punk)
00419 : parent_class_type(punk)
00420 {}
00421 #endif
00422
00424 ss_explicit_k interface_cast_noaddref(interface_pointer_type pi)
00425 : parent_class_type(pi)
00426 {}
00427
00428 #ifndef __STLSOFT_DOCUMENTATION_SKIP_SECTION
00429 ~interface_cast_noaddref() comstl_throw_0()
00430 {}
00431 #endif
00432
00433
00434 public:
00436 protected_interface_pointer_type operator -> () const
00437 {
00438 comstl_message_assert("Attempting to dereference null pointer. Exception model should not be null", NULL != get_pointer_());
00439
00440 return static_cast<protected_interface_pointer_type>(get_pointer_());
00441 }
00442
00443
00444 private:
00445 interface_cast_noaddref(class_type const &rhs);
00446 class_type const &operator =(class_type const &rhs);
00447
00448
00449 void *operator new(cs_size_t ) { return 0; }
00450 void operator delete(void * ) {}
00451 };
00452
00459 template< ss_typename_param_k I
00460 , ss_typename_param_k X = ignore_interface_cast_exception
00461 >
00462 class interface_cast_addref
00463 : protected interface_cast_base<I, addref_release<I>, X>
00464 {
00465 private:
00466 typedef interface_cast_base<I, addref_release<I>, X> parent_class_type;
00467 public:
00469 typedef interface_cast_addref<I, X> class_type;
00471 typedef ss_typename_type_k parent_class_type::interface_pointer_type interface_pointer_type;
00472
00473
00474 public:
00476 #ifdef __STLSOFT_CF_MEMBER_TEMPLATE_CTOR_SUPPORT
00477 template <ss_typename_param_k J>
00478 ss_explicit_k interface_cast_addref(J j)
00479 : parent_class_type(j)
00480 {}
00481 #else
00482 ss_explicit_k interface_cast_addref(LPUNKNOWN punk)
00483 : parent_class_type(punk)
00484 {}
00485 #endif
00486
00488 ss_explicit_k interface_cast_addref(interface_pointer_type pi)
00489 : parent_class_type(pi)
00490 {}
00491
00492
00493 public:
00495 operator interface_pointer_type ()
00496 {
00497 return get_pointer_();
00498 }
00499
00500
00501 private:
00502 interface_cast_addref(class_type const &rhs);
00503 class_type const &operator =(class_type const &rhs);
00504
00505
00506 void *operator new(cs_size_t ) { return 0; }
00507 void operator delete(void * ) {}
00508 };
00509
00510
00518 template< ss_typename_param_k I
00519 >
00520 class interface_cast_test
00521 : protected interface_cast_base<I, noaddref_release<I>, ignore_interface_cast_exception>
00522 {
00523 private:
00524 typedef interface_cast_base<I, noaddref_release<I>, ignore_interface_cast_exception> parent_class_type;
00525 public:
00527 typedef interface_cast_test<I> class_type;
00529 typedef ss_typename_type_k parent_class_type::interface_pointer_type interface_pointer_type;
00530 #ifdef __STLSOFT_CF_TEMPLATE_PARTIAL_SPECIALISATION_SUPPORT
00531
00532 typedef ss_typename_type_k parent_class_type::interface_type interface_type;
00533 typedef protect_refcount<interface_type> *protected_interface_pointer_type;
00534 #else
00535 typedef interface_pointer_type protected_interface_pointer_type;
00536 #endif // __STLSOFT_CF_TEMPLATE_PARTIAL_SPECIALISATION_SUPPORT
00537
00538
00539 public:
00541 #ifdef __STLSOFT_CF_MEMBER_TEMPLATE_CTOR_SUPPORT
00542 template <ss_typename_param_k J>
00543 ss_explicit_k interface_cast_test(J &j)
00544 : parent_class_type(j)
00545 {}
00546 #else
00547 ss_explicit_k interface_cast_test(LPUNKNOWN punk)
00548 : parent_class_type(punk)
00549 {}
00550 #endif
00551
00553 ss_explicit_k interface_cast_test(interface_pointer_type pi)
00554 : parent_class_type(pi)
00555 {}
00556
00557 #ifndef __STLSOFT_DOCUMENTATION_SKIP_SECTION
00558 ~interface_cast_test() comstl_throw_0()
00559 {}
00560 #endif
00561
00563 private:
00564 STLSOFT_DEFINE_OPERATOR_BOOL_TYPES_T(class_type, operator_bool_generator_type, operator_bool_type);
00565 public:
00571 operator operator_bool_type() const
00572 {
00573 return operator_bool_generator_type::translate(NULL != get_pointer_());
00574 }
00579 cs_bool_t operator !() const
00580 {
00581 return NULL == get_pointer_();
00582 }
00584
00585
00586 private:
00587 interface_cast_test(class_type const &rhs);
00588 class_type const &operator =(class_type const &rhs);
00589
00590
00591 void *operator new(cs_size_t ) { return 0; }
00592 void operator delete(void * ) {}
00593 };
00594
00595
00596
00597
00598
00599
00600
00601
00602
00603
00604 #endif
00605
00606
00607
00608
00609
00613 template< ss_typename_param_k I
00614 , ss_typename_param_k X
00615 >
00616 inline I get_ptr(comstl_ns_qual(interface_cast_noaddref)<I, X> &p)
00617 {
00618 return p.operator -> ();
00619 }
00620
00624 template< ss_typename_param_k I
00625 , ss_typename_param_k X
00626 >
00627 inline I const get_ptr(comstl_ns_qual(interface_cast_noaddref)<I, X> const &p)
00628 {
00629 return p.operator -> ();
00630 }
00631
00635 template< ss_typename_param_k I
00636 , ss_typename_param_k X
00637 >
00638 inline I get_ptr(comstl_ns_qual(interface_cast_addref)<I, X> &p)
00639 {
00640 return p;
00641 }
00642
00646 template< ss_typename_param_k I
00647 , ss_typename_param_k X
00648 >
00649 inline I const get_ptr(comstl_ns_qual(interface_cast_addref)<I, X> const &p)
00650 {
00651 return p;
00652 }
00653
00654
00655
00657
00658
00659
00660
00661
00662
00663
00664
00665
00666 #ifndef _COMSTL_NO_NAMESPACE
00667 # if defined(_STLSOFT_NO_NAMESPACE) || \
00668 defined(__STLSOFT_DOCUMENTATION_SKIP_SECTION)
00669 namespace comstl {
00670 # else
00671 namespace comstl_project {
00672 # endif
00673 #endif
00674
00676
00677
00678 #ifdef STLSOFT_UNITTEST
00679
00680 namespace unittest
00681 {
00682 ss_bool_t test_comstl_interface_cast(unittest_reporter *r)
00683 {
00684 using stlsoft::unittest::unittest_initialiser;
00685
00686 ss_bool_t bSuccess = true;
00687
00688 unittest_initialiser init(r, "COMSTL", "interface_cast", __FILE__);
00689
00690 LPSTREAM pstm;
00691 HRESULT hr = ::CreateStreamOnHGlobal(NULL, true, &pstm);
00692
00693 if(SUCCEEDED(hr))
00694 {
00695 if(!interface_cast_test<LPSTREAM>(pstm))
00696 {
00697 r->report("interface_cast_test failed to detect same type ", __LINE__);
00698 bSuccess = false;
00699 }
00700
00701 if(get_ptr(interface_cast_noaddref<LPSTREAM>(pstm)) != pstm)
00702 {
00703 r->report("interface_cast_noaddref did not cast to same type ", __LINE__);
00704 bSuccess = false;
00705 }
00706
00707 try
00708 {
00709 if(get_ptr(interface_cast_noaddref<LPSTORAGE>(pstm)) != NULL)
00710 {
00711 r->report("interface_cast_noaddref cast to wrong type ", __LINE__);
00712 bSuccess = false;
00713 }
00714 }
00715 catch(bad_interface_cast &x)
00716 {
00717 STLSOFT_SUPPRESS_UNUSED(x);
00718 }
00719
00720 LPSTREAM pstm2 = interface_cast_addref<LPSTREAM>(pstm);
00721 LPSTORAGE pstg = interface_cast_addref<LPSTORAGE>(pstm);
00722
00723 if(NULL == pstm2)
00724 {
00725 r->report("interface_cast_addref did not cast to same type ", __LINE__);
00726 bSuccess = false;
00727 }
00728 else
00729 {
00730 pstm2->Release();
00731 }
00732
00733 if(NULL != pstg)
00734 {
00735 r->report("interface_cast_addref cast to wrong type ", __LINE__);
00736 bSuccess = false;
00737 pstg->Release();
00738 }
00739
00740 pstm->Release();
00741 }
00742
00743 return bSuccess;
00744 }
00745
00746 unittest_registrar unittest_comstl_interface_cast(test_comstl_interface_cast);
00747
00748 }
00749
00750 #endif
00751
00752
00753
00754
00755
00756
00757
00758
00759
00760
00761
00762 #endif
00763
00764
00765
00766
00767
00768