williamr@2: williamr@2: #ifndef BOOST_MPL_HAS_XXX_HPP_INCLUDED williamr@2: #define BOOST_MPL_HAS_XXX_HPP_INCLUDED williamr@2: williamr@2: // Copyright Aleksey Gurtovoy 2002-2006 williamr@2: // Copyright David Abrahams 2002-2003 williamr@2: // williamr@2: // Distributed under the Boost Software License, Version 1.0. williamr@2: // (See accompanying file LICENSE_1_0.txt or copy at williamr@2: // http://www.boost.org/LICENSE_1_0.txt) williamr@2: // williamr@2: // See http://www.boost.org/libs/mpl for documentation. williamr@2: williamr@2: // $Source: /cvsroot/boost/boost/boost/mpl/has_xxx.hpp,v $ williamr@2: // $Date: 2006/11/09 01:05:31 $ williamr@2: // $Revision: 1.4.6.1 $ williamr@2: williamr@2: #include williamr@2: #include williamr@2: #include williamr@2: #include williamr@2: #include williamr@2: #include williamr@2: #include williamr@2: #include williamr@2: williamr@2: #include williamr@2: williamr@2: #if !defined(BOOST_MPL_CFG_NO_HAS_XXX) williamr@2: williamr@2: # if BOOST_WORKAROUND(BOOST_MSVC, <= 1300) williamr@2: williamr@2: // agurt, 11/sep/02: MSVC-specific version (< 7.1), based on a USENET williamr@2: // newsgroup's posting by John Madsen (comp.lang.c++.moderated, williamr@2: // 1999-11-12 19:17:06 GMT); the code is _not_ standard-conforming, but williamr@2: // it works way more reliably than the SFINAE-based implementation williamr@2: williamr@2: // Modified dwa 8/Oct/02 to handle reference types. williamr@2: williamr@2: # include williamr@2: # include williamr@2: williamr@2: namespace boost { namespace mpl { namespace aux { williamr@2: williamr@2: struct has_xxx_tag; williamr@2: williamr@2: #if BOOST_WORKAROUND(BOOST_MSVC, == 1300) williamr@2: template< typename U > struct msvc_incomplete_array williamr@2: { williamr@2: typedef char (&type)[sizeof(U) + 1]; williamr@2: }; williamr@2: #endif williamr@2: williamr@2: template< typename T > williamr@2: struct msvc_is_incomplete williamr@2: { williamr@2: // MSVC is capable of some kinds of SFINAE. If U is an incomplete williamr@2: // type, it won't pick the second overload williamr@2: static char tester(...); williamr@2: williamr@2: #if BOOST_WORKAROUND(BOOST_MSVC, == 1300) williamr@2: template< typename U > williamr@2: static typename msvc_incomplete_array::type tester(type_wrapper); williamr@2: #else williamr@2: template< typename U > williamr@2: static char (& tester(type_wrapper) )[sizeof(U)+1]; williamr@2: #endif williamr@2: williamr@2: BOOST_STATIC_CONSTANT(bool, value = williamr@2: sizeof(tester(type_wrapper())) == 1 williamr@2: ); williamr@2: }; williamr@2: williamr@2: template<> williamr@2: struct msvc_is_incomplete williamr@2: { williamr@2: BOOST_STATIC_CONSTANT(bool, value = false); williamr@2: }; williamr@2: williamr@2: }}} williamr@2: williamr@2: # define BOOST_MPL_HAS_XXX_TRAIT_NAMED_DEF_(trait, name, default_) \ williamr@2: template< typename T, typename name = ::boost::mpl::aux::has_xxx_tag > \ williamr@2: struct BOOST_PP_CAT(trait,_impl) : T \ williamr@2: { \ williamr@2: static boost::mpl::aux::no_tag \ williamr@2: test(void(*)(::boost::mpl::aux::has_xxx_tag)); \ williamr@2: \ williamr@2: static boost::mpl::aux::yes_tag test(...); \ williamr@2: \ williamr@2: BOOST_STATIC_CONSTANT(bool, value = \ williamr@2: sizeof(test(static_cast(0))) \ williamr@2: != sizeof(boost::mpl::aux::no_tag) \ williamr@2: ); \ williamr@2: typedef boost::mpl::bool_ type; \ williamr@2: }; \ williamr@2: \ williamr@2: template< typename T, typename fallback_ = boost::mpl::bool_ > \ williamr@2: struct trait \ williamr@2: : boost::mpl::if_c< \ williamr@2: boost::mpl::aux::msvc_is_incomplete::value \ williamr@2: , boost::mpl::bool_ \ williamr@2: , BOOST_PP_CAT(trait,_impl) \ williamr@2: >::type \ williamr@2: { \ williamr@2: }; \ williamr@2: \ williamr@2: BOOST_MPL_AUX_HAS_XXX_TRAIT_SPEC(trait, void) \ williamr@2: BOOST_MPL_AUX_HAS_XXX_TRAIT_SPEC(trait, bool) \ williamr@2: BOOST_MPL_AUX_HAS_XXX_TRAIT_SPEC(trait, char) \ williamr@2: BOOST_MPL_AUX_HAS_XXX_TRAIT_SPEC(trait, signed char) \ williamr@2: BOOST_MPL_AUX_HAS_XXX_TRAIT_SPEC(trait, unsigned char) \ williamr@2: BOOST_MPL_AUX_HAS_XXX_TRAIT_SPEC(trait, signed short) \ williamr@2: BOOST_MPL_AUX_HAS_XXX_TRAIT_SPEC(trait, unsigned short) \ williamr@2: BOOST_MPL_AUX_HAS_XXX_TRAIT_SPEC(trait, signed int) \ williamr@2: BOOST_MPL_AUX_HAS_XXX_TRAIT_SPEC(trait, unsigned int) \ williamr@2: BOOST_MPL_AUX_HAS_XXX_TRAIT_SPEC(trait, signed long) \ williamr@2: BOOST_MPL_AUX_HAS_XXX_TRAIT_SPEC(trait, unsigned long) \ williamr@2: BOOST_MPL_AUX_HAS_XXX_TRAIT_SPEC(trait, float) \ williamr@2: BOOST_MPL_AUX_HAS_XXX_TRAIT_SPEC(trait, double) \ williamr@2: BOOST_MPL_AUX_HAS_XXX_TRAIT_SPEC(trait, long double) \ williamr@2: /**/ williamr@2: williamr@2: # define BOOST_MPL_AUX_HAS_XXX_TRAIT_SPEC(trait, T) \ williamr@2: template<> struct trait \ williamr@2: { \ williamr@2: BOOST_STATIC_CONSTANT(bool, value = false); \ williamr@2: typedef boost::mpl::bool_ type; \ williamr@2: }; \ williamr@2: /**/ williamr@2: williamr@2: #if !defined(BOOST_NO_INTRINSIC_WCHAR_T) williamr@2: # define BOOST_MPL_HAS_XXX_TRAIT_NAMED_DEF(trait, name, unused) \ williamr@2: BOOST_MPL_HAS_XXX_TRAIT_NAMED_DEF_(trait, name, unused) \ williamr@2: BOOST_MPL_AUX_HAS_XXX_TRAIT_SPEC(trait, wchar_t) \ williamr@2: /**/ williamr@2: #else williamr@2: # define BOOST_MPL_HAS_XXX_TRAIT_NAMED_DEF(trait, name, unused) \ williamr@2: BOOST_MPL_HAS_XXX_TRAIT_NAMED_DEF_(trait, name, unused) \ williamr@2: /**/ williamr@2: #endif williamr@2: williamr@2: williamr@2: // SFINAE-based implementations below are derived from a USENET newsgroup's williamr@2: // posting by Rani Sharoni (comp.lang.c++.moderated, 2002-03-17 07:45:09 PST) williamr@2: williamr@2: # elif BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1400)) \ williamr@2: || BOOST_WORKAROUND(__IBMCPP__, <= 700) williamr@2: williamr@2: // MSVC 7.1+ & VACPP williamr@2: williamr@2: // agurt, 15/jun/05: replace overload-based SFINAE implementation with SFINAE williamr@2: // applied to partial specialization to fix some apparently random failures williamr@2: // (thanks to Daniel Wallin for researching this!) williamr@2: williamr@2: namespace boost { namespace mpl { namespace aux { williamr@2: template< typename T > struct msvc71_sfinae_helper { typedef void type; }; williamr@2: }}} williamr@2: williamr@2: # define BOOST_MPL_HAS_XXX_TRAIT_NAMED_DEF(trait, name, default_) \ williamr@2: template< typename T, typename U = void > \ williamr@2: struct BOOST_PP_CAT(trait,_impl_) \ williamr@2: { \ williamr@2: BOOST_STATIC_CONSTANT(bool, value = false); \ williamr@2: typedef boost::mpl::bool_ type; \ williamr@2: }; \ williamr@2: \ williamr@2: template< typename T > \ williamr@2: struct BOOST_PP_CAT(trait,_impl_)< \ williamr@2: T \ williamr@2: , typename boost::mpl::aux::msvc71_sfinae_helper< typename T::name >::type \ williamr@2: > \ williamr@2: { \ williamr@2: BOOST_STATIC_CONSTANT(bool, value = true); \ williamr@2: typedef boost::mpl::bool_ type; \ williamr@2: }; \ williamr@2: \ williamr@2: template< typename T, typename fallback_ = boost::mpl::bool_ > \ williamr@2: struct trait \ williamr@2: : BOOST_PP_CAT(trait,_impl_) \ williamr@2: { \ williamr@2: }; \ williamr@2: /**/ williamr@2: williamr@2: # else // other SFINAE-capable compilers williamr@2: williamr@2: # define BOOST_MPL_HAS_XXX_TRAIT_NAMED_DEF(trait, name, default_) \ williamr@2: template< typename T, typename fallback_ = boost::mpl::bool_ > \ williamr@2: struct trait \ williamr@2: { \ williamr@2: struct gcc_3_2_wknd \ williamr@2: { \ williamr@2: template< typename U > \ williamr@2: static boost::mpl::aux::yes_tag test( \ williamr@2: boost::mpl::aux::type_wrapper const volatile* \ williamr@2: , boost::mpl::aux::type_wrapper* = 0 \ williamr@2: ); \ williamr@2: \ williamr@2: static boost::mpl::aux::no_tag test(...); \ williamr@2: }; \ williamr@2: \ williamr@2: typedef boost::mpl::aux::type_wrapper t_; \ williamr@2: BOOST_STATIC_CONSTANT(bool, value = \ williamr@2: sizeof(gcc_3_2_wknd::test(static_cast(0))) \ williamr@2: == sizeof(boost::mpl::aux::yes_tag) \ williamr@2: ); \ williamr@2: typedef boost::mpl::bool_ type; \ williamr@2: }; \ williamr@2: /**/ williamr@2: williamr@2: # endif // BOOST_WORKAROUND(BOOST_MSVC, <= 1300) williamr@2: williamr@2: williamr@2: #else // BOOST_MPL_CFG_NO_HAS_XXX williamr@2: williamr@2: // placeholder implementation williamr@2: williamr@2: # define BOOST_MPL_HAS_XXX_TRAIT_NAMED_DEF(trait, name, default_) \ williamr@2: template< typename T, typename fallback_ = boost::mpl::bool_ > \ williamr@2: struct trait \ williamr@2: { \ williamr@2: BOOST_STATIC_CONSTANT(bool, value = fallback_::value); \ williamr@2: typedef fallback_ type; \ williamr@2: }; \ williamr@2: /**/ williamr@2: williamr@2: #endif williamr@2: williamr@2: #define BOOST_MPL_HAS_XXX_TRAIT_DEF(name) \ williamr@2: BOOST_MPL_HAS_XXX_TRAIT_NAMED_DEF(BOOST_PP_CAT(has_,name), name, false) \ williamr@2: /**/ williamr@2: williamr@2: #endif // BOOST_MPL_HAS_XXX_HPP_INCLUDED