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
00057 #ifndef COMSTL_INCL_COMSTL_CONVERSION_HPP_INTERFACE_CAST
00058 #define COMSTL_INCL_COMSTL_CONVERSION_HPP_INTERFACE_CAST
00059
00060 #ifndef STLSOFT_DOCUMENTATION_SKIP_SECTION
00061 # define COMSTL_VER_COMSTL_CONVERSION_HPP_INTERFACE_CAST_MAJOR 5
00062 # define COMSTL_VER_COMSTL_CONVERSION_HPP_INTERFACE_CAST_MINOR 2
00063 # define COMSTL_VER_COMSTL_CONVERSION_HPP_INTERFACE_CAST_REVISION 4
00064 # define COMSTL_VER_COMSTL_CONVERSION_HPP_INTERFACE_CAST_EDIT 117
00065 #endif
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081 #ifndef COMSTL_INCL_COMSTL_H_COMSTL
00082 # include <comstl/comstl.h>
00083 #endif
00084
00085 #if defined(STLSOFT_COMPILER_IS_MSVC) && \
00086 _MSC_VER < 1200
00087 # error comstl/conversion/interface_cast.hpp is not compatible with Visual C++ 5.0 or earlier
00088 #endif
00089
00090 #ifndef COMSTL_INCL_COMSTL_UTIL_H_REFCOUNT_FUNCTIONS
00091 # include <comstl/util/refcount_functions.h>
00092 #endif
00093 #ifndef COMSTL_INCL_COMSTL_UTIL_HPP_INTERFACE_TRAITS
00094 # include <comstl/util/interface_traits.hpp>
00095 #endif
00096 #ifdef STLSOFT_CF_EXCEPTION_SUPPORT
00097 # ifndef COMSTL_INCL_COMSTL_ERROR_HPP_BAD_INTERFACE_CAST
00098 # include <comstl/error/bad_interface_cast.hpp>
00099 # endif
00100 #endif
00101 #ifndef STLSOFT_INCL_STLSOFT_SMARTPTR_HPP_REF_PTR
00102 # include <stlsoft/smartptr/ref_ptr.hpp>
00103 #endif
00104 #ifndef STLSOFT_INCL_STLSOFT_UTIL_HPP_OPERATOR_BOOL
00105 # include <stlsoft/util/operator_bool.hpp>
00106 #endif
00107
00108
00109
00110
00111
00112 #ifndef _COMSTL_NO_NAMESPACE
00113 # if defined(_STLSOFT_NO_NAMESPACE) || \
00114 defined(STLSOFT_DOCUMENTATION_SKIP_SECTION)
00115
00116 namespace comstl
00117 {
00118 # else
00119
00120
00121 namespace stlsoft
00122 {
00123
00124 namespace comstl_project
00125 {
00126
00127 # endif
00128 #endif
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138 template <ss_typename_param_k I>
00139 inline I* simple_interface_cast(I* pi)
00140 {
00141 return pi;
00142 }
00143
00144
00145
00146
00147
00154
00155 struct ignore_interface_cast_exception
00156 {
00157 public:
00159 struct thrown_type
00160 {
00161 };
00162
00163 public:
00168 void operator ()(HRESULT hr, REFIID riid) stlsoft_throw_0()
00169 {
00170 STLSOFT_SUPPRESS_UNUSED(hr);
00171 STLSOFT_SUPPRESS_UNUSED(riid);
00172
00173
00174 }
00175 };
00176
00177 #ifdef STLSOFT_CF_EXCEPTION_SUPPORT
00178
00187
00188 struct throw_bad_interface_cast_exception
00189 {
00190 public:
00192 typedef bad_interface_cast thrown_type;
00193
00194 public:
00199 void operator ()(HRESULT hr, REFIID riid) stlsoft_throw_1(bad_interface_cast)
00200 {
00201 STLSOFT_THROW_X(bad_interface_cast(riid, hr));
00202 }
00203 };
00204
00205 #endif
00206
00213 template <ss_typename_param_k I>
00214 struct noaddref_release
00215 {
00216 public:
00220 void operator ()(I pi)
00221 {
00222 release(pi);
00223 }
00224 };
00225
00232 template <ss_typename_param_k I>
00233 struct addref_release
00234 {
00235 public:
00239 void operator ()(I pi)
00240 {
00241 STLSOFT_SUPPRESS_UNUSED(pi);
00242 }
00243 };
00244
00245
00246
00247
00248
00249
00250
00251
00252 #ifdef STLSOFT_CF_TEMPLATE_PARTIAL_SPECIALISATION_SUPPORT
00253
00254 # ifndef STLSOFT_DOCUMENTATION_SKIP_SECTION
00255
00256 template <ss_typename_param_k I>
00257 struct interface_pointer_traits;
00258
00259 template <ss_typename_param_k I>
00260 struct interface_pointer_traits<I*>
00261 {
00262 typedef I interface_type;
00263 };
00264
00265 # endif
00266
00273 template <ss_typename_param_k I>
00274 interface protect_refcount
00275 : public I
00276 {
00277 private:
00278 STDMETHOD_(ULONG, AddRef)()
00279 {
00280 I* pi = static_cast<I*>(this);
00281
00282 return pi->AddRef();
00283 }
00284 STDMETHOD_(ULONG, Release)()
00285 {
00286 I* pi = static_cast<I*>(this);
00287
00288 return pi->Release();
00289 }
00290 };
00291
00292 #endif
00293
00294
00295
00296
00297
00309
00310 template< ss_typename_param_k I
00311 , ss_typename_param_k R
00312 , ss_typename_param_k X
00313 >
00314 class interface_cast_base
00315 {
00318 public:
00320 typedef I interface_pointer_type;
00321 #ifdef STLSOFT_CF_TEMPLATE_PARTIAL_SPECIALISATION_SUPPORT
00323 typedef ss_typename_type_k interface_pointer_traits<I>::interface_type interface_type;
00324 #endif
00326 typedef R release_type;
00328 typedef X exception_policy_type;
00330 typedef ss_typename_type_k exception_policy_type::thrown_type thrown_type;
00332 typedef interface_cast_base<I, R, X> class_type;
00334
00337 protected:
00338 enum NullThrowPermission
00339 {
00340 allowNull
00341 , throwOnNull
00342 };
00344
00347 protected:
00349 #ifdef STLSOFT_CF_MEMBER_TEMPLATE_CTOR_SUPPORT
00350 template <ss_typename_param_k J>
00351 ss_explicit_k interface_cast_base(J &j, NullThrowPermission permission)
00352 : m_pi(do_cast(simple_interface_cast(j), permission))
00353 {}
00354 #else
00355 ss_explicit_k interface_cast_base(LPUNKNOWN punk, NullThrowPermission permission)
00356 : m_pi(do_cast(punk, permission))
00357 {}
00358 #endif
00359
00361 ss_explicit_k interface_cast_base(interface_pointer_type pi)
00362 : m_pi(pi)
00363 {
00364 addref(m_pi);
00365 }
00366
00368 ~interface_cast_base() stlsoft_throw_0()
00369 {
00370 if(NULL != m_pi)
00371 {
00372 release_type()(m_pi);
00373 }
00374 }
00376
00379 private:
00385 static interface_pointer_type do_cast(LPUNKNOWN punk, NullThrowPermission permission) stlsoft_throw_1(thrown_type)
00386 {
00387 interface_pointer_type pi;
00388
00389 if(NULL == punk)
00390 {
00391 if(throwOnNull == permission)
00392 {
00393 exception_policy_type()(E_INVALIDARG, IID_traits<interface_pointer_type>().iid());
00394
00395 COMSTL_MESSAGE_ASSERT("The derived class does not support null pointers, but the exception policy failed to throw an exception: the program's behaviour will be undefined!", 0);
00396 }
00397
00398 pi = NULL;
00399 }
00400 else
00401 {
00402 REFIID iid = IID_traits<interface_pointer_type>().iid();
00403 HRESULT hr = punk->QueryInterface(iid, reinterpret_cast<void**>(&pi));
00404
00405 if(FAILED(hr))
00406 {
00407 exception_policy_type()(hr, iid);
00408
00409 pi = NULL;
00410 }
00411 }
00412
00413 return pi;
00414 }
00416
00419 protected:
00421 interface_pointer_type const& get_pointer_()
00422 {
00423 return m_pi;
00424 }
00425
00427 interface_pointer_type get_pointer_() const
00428 {
00429 return m_pi;
00430 }
00432
00435 private:
00436 interface_pointer_type const m_pi;
00438
00441 protected:
00442 interface_cast_base(class_type const& rhs);
00443 private:
00444 class_type const& operator =(class_type const& rhs);
00446 };
00447
00448 #ifdef STLSOFT_CF_EXCEPTION_SUPPORT
00449
00461
00462 template< ss_typename_param_k I
00463 , ss_typename_param_k X = throw_bad_interface_cast_exception
00464 >
00465 class interface_cast_noaddref
00466 : protected interface_cast_base<I, noaddref_release<I>, X>
00467 {
00468 private:
00469 typedef interface_cast_base<I, noaddref_release<I>, X> parent_class_type;
00470 public:
00472 typedef interface_cast_noaddref<I, X> class_type;
00474 typedef ss_typename_type_k parent_class_type::interface_pointer_type interface_pointer_type;
00475 # ifdef STLSOFT_CF_TEMPLATE_PARTIAL_SPECIALISATION_SUPPORT
00477 typedef ss_typename_type_k parent_class_type::interface_type interface_type;
00478 typedef protect_refcount<interface_type>* protected_interface_pointer_type;
00479 # else
00480 typedef interface_pointer_type protected_interface_pointer_type;
00481 # endif
00482
00483 public:
00485 # ifdef STLSOFT_CF_MEMBER_TEMPLATE_CTOR_SUPPORT
00486 template <ss_typename_param_k J>
00487 ss_explicit_k interface_cast_noaddref(J &j)
00488 : parent_class_type(j, parent_class_type::throwOnNull)
00489 {
00490 COMSTL_MESSAGE_ASSERT("Cannot initialise with a null pointer. Program behaviour will be undefined when it this instance is dereference", NULL != this->parent_class_type::get_pointer_());
00491 }
00492 # else
00493 ss_explicit_k interface_cast_noaddref(LPUNKNOWN punk)
00494 : parent_class_type(punk, parent_class_type::throwOnNull)
00495 {
00496 COMSTL_MESSAGE_ASSERT("Cannot initialise with a null pointer. Program behaviour will be undefined when it this instance is dereference", NULL != this->parent_class_type::get_pointer_());
00497 }
00498 # endif
00499
00501 ss_explicit_k interface_cast_noaddref(interface_pointer_type pi)
00502 : parent_class_type(pi, parent_class_type::throwOnNull)
00503 {
00504 COMSTL_MESSAGE_ASSERT("Cannot initialise with a null pointer. Program behaviour will be undefined when it this instance is dereference", NULL != this->parent_class_type::get_pointer_());
00505 }
00506
00507 # ifndef STLSOFT_DOCUMENTATION_SKIP_SECTION
00508 ~interface_cast_noaddref() stlsoft_throw_0()
00509 {}
00510 # endif
00511
00512
00513 public:
00515 protected_interface_pointer_type operator -> () const
00516 {
00517 COMSTL_MESSAGE_ASSERT("Attempting to dereference null pointer. Exception model should not be null", NULL != this->parent_class_type::get_pointer_());
00518
00519 return static_cast<protected_interface_pointer_type>(this->parent_class_type::get_pointer_());
00520 }
00521
00522
00523 private:
00524 interface_cast_noaddref(class_type const& rhs);
00525 class_type const& operator =(class_type const& rhs);
00526
00527
00528 void* operator new(cs_size_t ) { return 0; }
00529 void operator delete(void* ) {}
00530 };
00531
00532 #endif
00533
00543
00544 template< ss_typename_param_k I
00545 , ss_typename_param_k X = ignore_interface_cast_exception
00546 >
00547 class interface_cast_addref
00548 : protected interface_cast_base<I, addref_release<I>, X>
00549 {
00550 private:
00551 typedef interface_cast_base<I, addref_release<I>, X> parent_class_type;
00552 public:
00554 typedef interface_cast_addref<I, X> class_type;
00556 typedef ss_typename_type_k parent_class_type::interface_pointer_type interface_pointer_type;
00557
00558 public:
00560 #ifdef STLSOFT_CF_MEMBER_TEMPLATE_CTOR_SUPPORT
00561 template <ss_typename_param_k J>
00562 ss_explicit_k interface_cast_addref(J j)
00563 : parent_class_type(j, parent_class_type::allowNull)
00564 {}
00565 #else
00566 ss_explicit_k interface_cast_addref(LPUNKNOWN punk)
00567 : parent_class_type(punk, parent_class_type::allowNull)
00568 {}
00569 #endif
00570
00572 ss_explicit_k interface_cast_addref(interface_pointer_type pi)
00573 : parent_class_type(pi, parent_class_type::allowNull)
00574 {}
00575
00576 #ifndef STLSOFT_DOCUMENTATION_SKIP_SECTION
00577 ~interface_cast_addref() stlsoft_throw_0()
00578 {}
00579 #endif
00580
00581
00582 public:
00584 operator interface_pointer_type ()
00585 {
00586 return this->parent_class_type::get_pointer_();
00587 }
00588
00589
00590 private:
00591 interface_cast_addref(class_type const& rhs);
00592 class_type const& operator =(class_type const& rhs);
00593
00594
00595 void* operator new(cs_size_t ) { return 0; }
00596 void operator delete(void* ) {}
00597 };
00598
00599
00600 #ifndef STLSOFT_DOCUMENTATION_SKIP_SECTION
00601
00602
00603 template< ss_typename_param_k I
00604 >
00605 class interface_cast_tester
00606 : protected interface_cast_base<I, noaddref_release<I>, ignore_interface_cast_exception>
00607 {
00608 private:
00609 typedef interface_cast_base<I, noaddref_release<I>, ignore_interface_cast_exception> parent_class_type;
00610 public:
00612 typedef interface_cast_tester<I> class_type;
00614 typedef ss_typename_type_k parent_class_type::interface_pointer_type interface_pointer_type;
00615 #ifdef STLSOFT_CF_TEMPLATE_PARTIAL_SPECIALISATION_SUPPORT
00617 typedef ss_typename_type_k parent_class_type::interface_type interface_type;
00618 typedef protect_refcount<interface_type>* protected_interface_pointer_type;
00619 #else
00620 typedef interface_pointer_type protected_interface_pointer_type;
00621 #endif
00622
00623 public:
00625 #ifdef STLSOFT_CF_MEMBER_TEMPLATE_CTOR_SUPPORT
00626 template <ss_typename_param_k J>
00627 ss_explicit_k interface_cast_tester(J &j)
00628 : parent_class_type(j, parent_class_type::allowNull)
00629 {}
00630 #else
00631 ss_explicit_k interface_cast_tester(LPUNKNOWN punk)
00632 : parent_class_type(punk, parent_class_type::allowNull)
00633 {}
00634 #endif
00635
00637 ss_explicit_k interface_cast_tester(interface_pointer_type pi)
00638 : parent_class_type(pi, parent_class_type::allowNull)
00639 {}
00640
00641 #ifndef STLSOFT_DOCUMENTATION_SKIP_SECTION
00642 ~interface_cast_tester() stlsoft_throw_0()
00643 {}
00644 #endif
00645
00648 private:
00649 STLSOFT_DEFINE_OPERATOR_BOOL_TYPES_T(class_type, operator_bool_generator_type, operator_bool_type);
00650 public:
00655 operator operator_bool_type() const
00656 {
00657 return operator_bool_generator_type::translate(NULL != this->parent_class_type::get_pointer_());
00658 }
00663 cs_bool_t operator !() const
00664 {
00665 return NULL == this->parent_class_type::get_pointer_();
00666 }
00668
00669
00670 private:
00671 interface_cast_tester(class_type const& rhs);
00672 class_type const& operator =(class_type const& rhs);
00673
00674
00675 void* operator new(cs_size_t ) { return 0; }
00676 void operator delete(void* ) {}
00677 };
00678
00679 #endif
00680
00700 template< ss_typename_param_k IDest
00701 , ss_typename_param_k ISrc
00702 >
00703 #if defined(STLSOFT_COMPILER_IS_MSVC) && \
00704 _MSC_VER < 1300
00705
00706
00707 inline cs_bool_t interface_cast_test(ISrc* src, IDest* = NULL)
00708 #else
00709 inline cs_bool_t interface_cast_test(ISrc* src)
00710 #endif
00711 {
00712 interface_cast_tester<IDest> b(src);
00713
00714 return !!b;
00715 }
00716
00737 template< ss_typename_param_k IDest
00738 , ss_typename_param_k ISrc
00739 >
00740 #if defined(STLSOFT_COMPILER_IS_MSVC) && \
00741 _MSC_VER < 1300
00742
00743
00744 inline cs_bool_t interface_cast_test(stlsoft_ns_qual(ref_ptr)<ISrc> &src, IDest* = NULL)
00745 #else
00746 inline cs_bool_t interface_cast_test(stlsoft_ns_qual(ref_ptr)<ISrc> &src)
00747 #endif
00748 {
00749 return interface_cast_test<IDest*>(src.get());
00750 }
00751
00752
00753 #ifdef STLSOFT_CF_EXCEPTION_SUPPORT
00754
00787 template< ss_typename_param_k IDest
00788 , ss_typename_param_k ISrc
00789 >
00790 inline stlsoft_ns_qual(ref_ptr)<IDest> interface_cast(ISrc* src)
00791 {
00792 interface_cast_addref<IDest*, throw_bad_interface_cast_exception> ptr(src);
00793
00794 return stlsoft_ns_qual(ref_ptr)<IDest>(static_cast<IDest*>(ptr), false);
00795 }
00796
00829 template< ss_typename_param_k IDest
00830 , ss_typename_param_k ISrc
00831 >
00832 inline stlsoft_ns_qual(ref_ptr)<IDest> interface_cast(stlsoft_ns_qual(ref_ptr)<ISrc> src)
00833 {
00834 return interface_cast<IDest>(src.get());
00835 }
00836
00837 #endif
00838
00839
00862 template< ss_typename_param_k IDest
00863 , ss_typename_param_k ISrc
00864 >
00865 inline stlsoft_ns_qual(ref_ptr)<IDest> try_interface_cast(ISrc* src)
00866 {
00867 interface_cast_addref<IDest*> ptr(src);
00868
00869 return stlsoft_ns_qual(ref_ptr)<IDest>(static_cast<IDest*>(ptr), false);
00870 }
00871
00882 template< ss_typename_param_k IDest
00883 , ss_typename_param_k ISrc
00884 >
00885 inline stlsoft_ns_qual(ref_ptr)<IDest> try_interface_cast(stlsoft_ns_qual(ref_ptr)<ISrc> src)
00886 {
00887 return try_interface_cast<IDest>(src.get());
00888 }
00889
00890
00891
00892
00893
00894 #ifdef STLSOFT_CF_EXCEPTION_SUPPORT
00895
00896 # if !defined(STLSOFT_COMPILER_IS_COMO) && \
00897 !defined(STLSOFT_COMPILER_IS_GCC)
00898
00905 template< ss_typename_param_k I
00906 , ss_typename_param_k X
00907 >
00908 inline I get_ptr(comstl_ns_qual(interface_cast_noaddref)<I, X> &p)
00909 {
00910 return p.operator -> ();
00911 }
00912 # endif
00913
00920 template< ss_typename_param_k I
00921 , ss_typename_param_k X
00922 >
00923 inline I get_ptr(comstl_ns_qual(interface_cast_noaddref)<I, X> const& p)
00924 {
00925 return p.operator -> ();
00926 }
00927
00928 #endif
00929
00936 template< ss_typename_param_k I
00937 , ss_typename_param_k X
00938 >
00939 inline I get_ptr(comstl_ns_qual(interface_cast_addref)<I, X> &p)
00940 {
00941 return p;
00942 }
00943
00950 template< ss_typename_param_k I
00951 , ss_typename_param_k X
00952 >
00953 inline I const get_ptr(comstl_ns_qual(interface_cast_addref)<I, X> const& p)
00954 {
00955 return p;
00956 }
00957
00958
00959
00960
00961
00962 #ifndef STLSOFT_DOCUMENTATION_SKIP_SECTION
00963
00964 # ifdef STLSOFT_CF_EXCEPTION_SUPPORT
00965
00966 template< ss_typename_param_k I
00967 , ss_typename_param_k X
00968 >
00969 inline cs_bool_t is_empty(comstl_ns_qual(interface_cast_noaddref)<I, X> const& p)
00970 {
00971 return NULL != get_ptr(p);
00972 }
00973
00974 # endif
00975
00976 template< ss_typename_param_k I
00977 , ss_typename_param_k X
00978 >
00979 inline cs_bool_t is_empty(comstl_ns_qual(interface_cast_addref)<I, X> const& p)
00980 {
00981 return NULL != get_ptr(p);
00982 }
00983
00984 #endif
00985
00987
00988
00989 #ifdef STLSOFT_UNITTEST
00990 # include "./unittest/interface_cast_unittest_.h"
00991 #endif
00992
00993
00994
00995 #ifndef _COMSTL_NO_NAMESPACE
00996 # if defined(_STLSOFT_NO_NAMESPACE) || \
00997 defined(STLSOFT_DOCUMENTATION_SKIP_SECTION)
00998 }
00999 # else
01000 }
01001 }
01002 # endif
01003 #endif
01004
01005
01006
01007
01008
01009
01010
01011
01012
01013 #ifndef _COMSTL_NO_NAMESPACE
01014 # if !defined(_STLSOFT_NO_NAMESPACE) && \
01015 !defined(STLSOFT_DOCUMENTATION_SKIP_SECTION)
01016 namespace stlsoft
01017 {
01018 # else
01019
01020 # endif
01021
01022 using ::comstl::get_ptr;
01023
01024 #ifndef STLSOFT_DOCUMENTATION_SKIP_SECTION
01025
01026 using ::comstl::is_empty;
01027
01028 #endif
01029
01030 # if !defined(_STLSOFT_NO_NAMESPACE) && \
01031 !defined(STLSOFT_DOCUMENTATION_SKIP_SECTION)
01032 }
01033 # else
01034
01035 # endif
01036 #endif
01037
01038
01039
01040 #endif
01041
01042