📄 interface_cast.hpp
字号:
}
\endcode
*/
template< ss_typename_param_k IDest
, ss_typename_param_k ISrc
>
#if defined(STLSOFT_COMPILER_IS_MSVC) && \
_MSC_VER < 1300
// This workaround is required to stop the poor dear from instantiating
// interface_cast_tester on ISrc rather than IDest.
inline cs_bool_t interface_cast_test(ISrc *src, IDest * = NULL)
#else /* ? compiler */
inline cs_bool_t interface_cast_test(ISrc *src)
#endif /* compiler */
{
interface_cast_tester<IDest> b(src);
return !!b;
}
/** \brief Determines whether an interface is available on an object
*
* \ingroup group__library__conversion
*
\code
stlsoft::ref_ptr<IStream> stm = . . .
if(comstl::interface_cast_test<IStorage>(stm))
{
printf("Wrapper object has IStorage interface\n");
}
else
{
printf("Wrapper object does not have IStorage interface\n");
}
\endcode
*
* \param src wrapper instance holding the object whose capabilities
* will be tested. May be empty.
*/
template< ss_typename_param_k IDest
, ss_typename_param_k ISrc
>
#if defined(STLSOFT_COMPILER_IS_MSVC) && \
_MSC_VER < 1300
// This workaround is required to stop the poor dear from instantiating
// interface_cast_tester on ISrc rather than IDest.
inline cs_bool_t interface_cast_test(stlsoft_ns_qual(ref_ptr)<ISrc> &src, IDest * = NULL)
#else /* ? compiler */
inline cs_bool_t interface_cast_test(stlsoft_ns_qual(ref_ptr)<ISrc> &src)
#endif /* compiler */
{
return interface_cast_test<IDest*>(src.get());
}
#ifdef STLSOFT_CF_EXCEPTION_SUPPORT
/** \brief Casts a raw interface pointer to a wrapped instance.
*
* \ingroup group__library__conversion
*
\code
IStream *stm = . . .
try
{
stlsoft::ref_ptr<IStorage> stg = comstl::interface_cast<IStorage>(stm);
printf("Object has IStorage interface\n");
}
catch(comstl::bad_interface_cast &)
{
printf("Object does not have IStorage interface\n");
}
\endcode
*
* \note For technical reasons, the cast destination type differs from the
* conventional behaviour. Rather than specifying the actual resultant
* type, e.g. <code>stlsoft::ref_ptr<IStream></code>, just the destination
* interface type must be specified, e.g.
* <code>interface_cast<IStream></code>.
*
* \exception comstl::bad_interface_cast When compiling with exception -
* detected when <code>STLSOFT_CF_EXCEPTION_SUPPORT</code> is defined -
* this will throw an instance of comstl::bad_interface_cast if the
* requested interface cannot be acquired. When compiling absent exception
* support, this cast function is not defined; instead use
* comstl::try_interface_cast.
*/
template< ss_typename_param_k IDest
, ss_typename_param_k ISrc
>
inline stlsoft_ns_qual(ref_ptr)<IDest> interface_cast(ISrc *src)
{
interface_cast_addref<IDest*, throw_bad_interface_cast_exception> ptr(src); // This has to be separate, otherwise G++ has a spit
return stlsoft_ns_qual(ref_ptr)<IDest>(static_cast<IDest*>(ptr), true);
}
/** \brief Casts between instances of wrapped instances
*
* \ingroup group__library__conversion
*
\code
stlsoft::ref_ptr<IStream> stm = . . .
try
{
stlsoft::ref_ptr<IStorage> stg = comstl::interface_cast<IStorage>(stm);
printf("Wrapper object has IStorage interface\n");
}
catch(comstl::bad_interface_cast &)
{
printf("Wrapper object does not have IStorage interface\n");
}
\endcode
*
* \note For technical reasons, the cast destination type differs from the
* conventional behaviour. Rather than specifying the actual resultant
* type, e.g. <code>stlsoft::ref_ptr<IStream></code>, just the destination
* interface type must be specified, e.g.
* <code>interface_cast<IStream></code>.
*
* \exception comstl::bad_interface_cast When compiling with exception -
* detected when <code>STLSOFT_CF_EXCEPTION_SUPPORT</code> is defined -
* this will throw an instance of comstl::bad_interface_cast if the
* requested interface cannot be acquired. When compiling absent exception
* support, this cast function is not defined; instead use
* comstl::try_interface_cast.
*/
template< ss_typename_param_k IDest
, ss_typename_param_k ISrc
>
inline stlsoft_ns_qual(ref_ptr)<IDest> interface_cast(stlsoft_ns_qual(ref_ptr)<ISrc> src)
{
return interface_cast<IDest>(src.get());
}
#endif /* STLSOFT_CF_EXCEPTION_SUPPORT */
/** \brief Attempts to cast a raw interface pointer to a wrapped instance.
*
* \ingroup group__library__conversion
*
\code
IStream *pstm = . . .
stlsoft::ref_ptr<IStorage> stg = comstl::interface_cast<IStorage>(pstm);
if(!stg.empty())
{
. . . // use stg->
}
\endcode
*
* \note For technical reasons, the cast destination type differs from the
* conventional behaviour. Rather than specifying the actual resultant
* type, e.g. <code>stlsoft::ref_ptr<IStream></code>, just the destination
* interface type must be specified, e.g.
* <code>interface_cast<IStream></code>.
*
* \return
*/
template< ss_typename_param_k IDest
, ss_typename_param_k ISrc
>
inline stlsoft_ns_qual(ref_ptr)<IDest> try_interface_cast(ISrc *src)
{
interface_cast_addref<IDest*> ptr(src); // This has to be separate, otherwise G++ has a spit
return stlsoft_ns_qual(ref_ptr)<IDest>(static_cast<IDest*>(ptr), true);
}
/** \brief Attempts to cast between instances of wrapped instances
*
* \ingroup group__library__conversion
*
* \note For technical reasons, the cast destination type differs from the
* conventional behaviour. Rather than specifying the actual resultant
* type, e.g. <code>stlsoft::ref_ptr<IStream></code>, just the destination
* interface type must be specified, e.g.
* <code>interface_cast<IStream></code>.
*/
template< ss_typename_param_k IDest
, ss_typename_param_k ISrc
>
inline stlsoft_ns_qual(ref_ptr)<IDest> try_interface_cast(stlsoft_ns_qual(ref_ptr)<ISrc> src)
{
return try_interface_cast<IDest>(src.get());
}
/* /////////////////////////////////////////////////////////////////////////
* Shims
*/
#ifdef STLSOFT_CF_EXCEPTION_SUPPORT
# if !defined(STLSOFT_COMPILER_IS_COMO) && \
!defined(STLSOFT_COMPILER_IS_GCC)
/** \brief Attribute shim to retrieve the interface pointer of the given cast instance
*
* \ingroup group__concept__shim__pointer_attribute__get_ptr
*
* \param p The cast instance
*/
template< ss_typename_param_k I
, ss_typename_param_k X
>
inline I get_ptr(comstl_ns_qual(interface_cast_noaddref)<I, X> &p)
{
return p.operator -> ();
}
# endif /* compiler */
/** \brief Attribute shim to retrieve the interface pointer of the given cast instance
*
* \ingroup group__concept__shim__pointer_attribute__get_ptr
*
* \param p The cast instance
*/
template< ss_typename_param_k I
, ss_typename_param_k X
>
inline I get_ptr(comstl_ns_qual(interface_cast_noaddref)<I, X> const& p)
{
return p.operator -> ();
}
#endif /* STLSOFT_CF_EXCEPTION_SUPPORT */
/** \brief Attribute shim to retrieve the interface pointer of the given cast instance
*
* \ingroup group__concept__shim__pointer_attribute__get_ptr
*
* \param p The cast instance
*/
template< ss_typename_param_k I
, ss_typename_param_k X
>
inline I get_ptr(comstl_ns_qual(interface_cast_addref)<I, X> &p)
{
return p;
}
/** \brief Attribute shim to retrieve the interface pointer of the given cast instance
*
* \ingroup group__concept__shim__pointer_attribute__get_ptr
*
* \param p The cast instance
*/
template< ss_typename_param_k I
, ss_typename_param_k X
>
inline I const get_ptr(comstl_ns_qual(interface_cast_addref)<I, X> const& p)
{
return p;
}
/* /////////////////////////////////////////////////////////////////////////
* Deprecated Shims
*/
#ifndef STLSOFT_DOCUMENTATION_SKIP_SECTION
# ifdef STLSOFT_CF_EXCEPTION_SUPPORT
template< ss_typename_param_k I
, ss_typename_param_k X
>
inline cs_bool_t is_empty(comstl_ns_qual(interface_cast_noaddref)<I, X> const& p)
{
return NULL != get_ptr(p);
}
# endif /* STLSOFT_CF_EXCEPTION_SUPPORT */
template< ss_typename_param_k I
, ss_typename_param_k X
>
inline cs_bool_t is_empty(comstl_ns_qual(interface_cast_addref)<I, X> const& p)
{
return NULL != get_ptr(p);
}
#endif /* !STLSOFT_DOCUMENTATION_SKIP_SECTION */
////////////////////////////////////////////////////////////////////////////
// Unit-testing
#ifdef STLSOFT_UNITTEST
# include "./unittest/interface_cast_unittest_.h"
#endif /* STLSOFT_UNITTEST */
/* ////////////////////////////////////////////////////////////////////// */
#ifndef _COMSTL_NO_NAMESPACE
# if defined(_STLSOFT_NO_NAMESPACE) || \
defined(STLSOFT_DOCUMENTATION_SKIP_SECTION)
} // namespace comstl
# else
} // namespace comstl_project
} // namespace stlsoft
# endif /* _STLSOFT_NO_NAMESPACE */
#endif /* !_COMSTL_NO_NAMESPACE */
/* /////////////////////////////////////////////////////////////////////////
* Namespace
*
* The string access shims exist either in the stlsoft namespace, or in the
* global namespace. This is required by the lookup rules.
*
*/
#ifndef _COMSTL_NO_NAMESPACE
# if !defined(_STLSOFT_NO_NAMESPACE) && \
!defined(STLSOFT_DOCUMENTATION_SKIP_SECTION)
namespace stlsoft
{
# else /* ? _STLSOFT_NO_NAMESPACE */
/* There is no stlsoft namespace, so must define in the global namespace */
# endif /* !_STLSOFT_NO_NAMESPACE */
using ::comstl::get_ptr;
#ifndef STLSOFT_DOCUMENTATION_SKIP_SECTION
using ::comstl::is_empty;
#endif /* !STLSOFT_DOCUMENTATION_SKIP_SECTION */
# if !defined(_STLSOFT_NO_NAMESPACE) && \
!defined(STLSOFT_DOCUMENTATION_SKIP_SECTION)
} // namespace stlsoft
# else /* ? _STLSOFT_NO_NAMESPACE */
/* There is no stlsoft namespace, so must define in the global namespace */
# endif /* !_STLSOFT_NO_NAMESPACE */
#endif /* !_COMSTL_NO_NAMESPACE */
/* ////////////////////////////////////////////////////////////////////// */
#endif /* !COMSTL_INCL_COMSTL_CONVERSION_HPP_INTERFACE_CAST */
/* ////////////////////////////////////////////////////////////////////// */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -