boost/intrusive/detail/has_member_function_callable_with.hpp
//////////////////////////////////////////////////////////////////////////////
//
// (C) Copyright Ion Gaztanaga 2011-2011. Distributed under the Boost
// Software License, Version 1.0. (See accompanying file
// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
// See http://www.boost.org/libs/intrusive for documentation.
//
//////////////////////////////////////////////////////////////////////////////
// sample.h
#if !BOOST_PP_IS_ITERATING
#ifndef BOOST_INTRUSIVE_DETAIL_HAS_MEMBER_FUNCTION_CALLABLE_WITH_DETAILS_INCLUDED
#define BOOST_INTRUSIVE_DETAIL_HAS_MEMBER_FUNCTION_CALLABLE_WITH_DETAILS_INCLUDED
#include <boost/intrusive/detail/config_begin.hpp>
#include <boost/intrusive/detail/workaround.hpp>
#include <boost/intrusive/detail/preprocessor.hpp>
#include <boost/static_assert.hpp>
#include <boost/move/move.hpp>
//Mark that we don't support 0 arg calls due to compiler ICE in GCC 3.4/4.0/4.1 and
//wrong SFINAE for GCC 4.2/4.3
#if defined(__GNUC__) && !defined(__clang__) && ((__GNUC__*100 + __GNUC_MINOR__*10) >= 340) && ((__GNUC__*100 + __GNUC_MINOR__*10) <= 430)
#define BOOST_INTRUSIVE_DETAIL_HAS_MEMBER_FUNCTION_CALLABLE_WITH_0_ARGS_UNSUPPORTED
#elif defined(BOOST_INTEL) && (BOOST_INTEL < 1200 )
#define BOOST_INTRUSIVE_DETAIL_HAS_MEMBER_FUNCTION_CALLABLE_WITH_0_ARGS_UNSUPPORTED
#endif
namespace boost_intrusive_has_member_function_callable_with {
struct dont_care
{
dont_care(...);
};
struct private_type
{
static private_type p;
private_type const &operator,(int) const;
};
typedef char yes_type; // sizeof(yes_type) == 1
struct no_type{ char dummy[2]; }; // sizeof(no_type) == 2
template<typename T>
no_type is_private_type(T const &);
yes_type is_private_type(private_type const &);
} //boost_intrusive_has_member_function_callable_with
#include <boost/intrusive/detail/config_end.hpp>
#endif //BOOST_INTRUSIVE_DETAIL_HAS_MEMBER_FUNCTION_CALLABLE_WITH_DETAILS_INCLUDED
#else //!BOOST_PP_IS_ITERATING
#ifndef BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME
#error "BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME not defined!"
#endif
#ifndef BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_BEGIN
#error "BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_BEGIN not defined!"
#endif
#ifndef BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_END
#error "BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_END not defined!"
#endif
#if BOOST_PP_ITERATION_START() != 0
#error "BOOST_PP_ITERATION_START() must be zero (0)"
#endif
#if BOOST_PP_ITERATION() == 0
BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_BEGIN
template <typename Type>
class BOOST_PP_CAT(has_member_function_named_, BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME)
{
struct BaseMixin
{
void BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME();
};
struct Base : public Type, public BaseMixin { Base(); };
template <typename T, T t> class Helper{};
template <typename U>
static boost_intrusive_has_member_function_callable_with::no_type deduce
(U*, Helper<void (BaseMixin::*)(), &U::BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME>* = 0);
static boost_intrusive_has_member_function_callable_with::yes_type deduce(...);
public:
static const bool value =
sizeof(boost_intrusive_has_member_function_callable_with::yes_type) == sizeof(deduce((Base*)(0)));
};
#if !defined(BOOST_INTRUSIVE_PERFECT_FORWARDING)
template<typename Fun, bool HasFunc
BOOST_PP_ENUM_TRAILING(BOOST_PP_ITERATION_FINISH(), BOOST_INTRUSIVE_PP_TEMPLATE_PARAM_VOID_DEFAULT, _)>
struct BOOST_PP_CAT(BOOST_PP_CAT(has_member_function_callable_with_, BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME), _impl);
//!
template<typename Fun BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PP_ITERATION_FINISH(), class P)>
struct BOOST_PP_CAT(BOOST_PP_CAT(has_member_function_callable_with_, BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME), _impl)
<Fun, false BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PP_ITERATION_FINISH(), P)>
{
static const bool value = false;
};
//!
#if !defined(_MSC_VER) || (_MSC_VER != 1600)
#if defined(BOOST_INTRUSIVE_DETAIL_HAS_MEMBER_FUNCTION_CALLABLE_WITH_0_ARGS_UNSUPPORTED)
template<typename Fun>
struct BOOST_PP_CAT(BOOST_PP_CAT(has_member_function_callable_with_, BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME),_impl)
<Fun, true BOOST_PP_ENUM_TRAILING(BOOST_PP_SUB(BOOST_PP_ITERATION_FINISH(), BOOST_PP_ITERATION()), BOOST_INTRUSIVE_PP_IDENTITY, void)>
{
//Mark that we don't support 0 arg calls due to compiler ICE in GCC 3.4/4.0/4.1 and
//wrong SFINAE for GCC 4.2/4.3
static const bool value = true;
};
#else
//Special case for 0 args
template< class F
, std::size_t N =
sizeof((boost::move_detail::declval<F>().
BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME (), 0))>
struct BOOST_PP_CAT(zeroarg_checker_, BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME)
{
boost_intrusive_has_member_function_callable_with::yes_type dummy;
BOOST_PP_CAT(zeroarg_checker_, BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME)(int);
};
//For buggy compilers like MSVC 7.1+ ((F*)0)->func() does not
//SFINAE-out the zeroarg_checker_ instantiation but sizeof yields to 0.
template<class F>
struct BOOST_PP_CAT(zeroarg_checker_, BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME)<F, 0>
{
boost_intrusive_has_member_function_callable_with::no_type dummy;
BOOST_PP_CAT(zeroarg_checker_, BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME)(int);
};
template<typename Fun>
struct BOOST_PP_CAT(BOOST_PP_CAT(has_member_function_callable_with_, BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME),_impl)
<Fun, true BOOST_PP_ENUM_TRAILING(BOOST_PP_SUB(BOOST_PP_ITERATION_FINISH(), BOOST_PP_ITERATION()), BOOST_INTRUSIVE_PP_IDENTITY, void)>
{
template<class U>
static BOOST_PP_CAT(zeroarg_checker_, BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME)<U>
Test(BOOST_PP_CAT(zeroarg_checker_, BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME)<U>*);
template <class U>
static boost_intrusive_has_member_function_callable_with::no_type Test(...);
static const bool value = sizeof(Test< Fun >(0))
== sizeof(boost_intrusive_has_member_function_callable_with::yes_type);
};
#endif
#else //#if !defined(_MSC_VER) || (_MSC_VER != 1600)
template<typename Fun>
struct BOOST_PP_CAT(BOOST_PP_CAT(has_member_function_callable_with_, BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME),_impl)
<Fun, true BOOST_PP_ENUM_TRAILING(BOOST_PP_SUB(BOOST_PP_ITERATION_FINISH(), BOOST_PP_ITERATION()), BOOST_INTRUSIVE_PP_IDENTITY, void)>
{
template<class U>
static decltype( boost::move_detail::declval<Fun>().BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME()
, boost_intrusive_has_member_function_callable_with::yes_type())
Test(Fun*);
template<class U>
static boost_intrusive_has_member_function_callable_with::no_type Test(...);
static const bool value = sizeof(Test<Fun>(0))
== sizeof(boost_intrusive_has_member_function_callable_with::yes_type);
};
#endif //#if !defined(_MSC_VER) || (_MSC_VER != 1600)
#else //#if !defined(BOOST_INTRUSIVE_PERFECT_FORWARDING)
template<typename Fun, bool HasFunc, class ...Args>
struct BOOST_PP_CAT(BOOST_PP_CAT(has_member_function_callable_with_, BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME),_impl);
template<typename Fun, class ...Args>
struct BOOST_PP_CAT(BOOST_PP_CAT(has_member_function_callable_with_, BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME),_impl)
<Fun, false, Args...>
{
static const bool value = false;
};
//Special case for 0 args
template< class F
, std::size_t N =
sizeof((boost::move_detail::declval<F>().
BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME (), 0))>
struct BOOST_PP_CAT(zeroarg_checker_, BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME)
{
boost_intrusive_has_member_function_callable_with::yes_type dummy;
BOOST_PP_CAT(zeroarg_checker_, BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME)(int);
};
//For buggy compilers like MSVC 7.1+ ((F*)0)->func() does not
//SFINAE-out the zeroarg_checker_ instantiation but sizeof yields to 0.
template<class F>
struct BOOST_PP_CAT(zeroarg_checker_, BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME)<F, 0>
{
boost_intrusive_has_member_function_callable_with::no_type dummy;
BOOST_PP_CAT(zeroarg_checker_, BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME)(int);
};
template<typename Fun>
struct BOOST_PP_CAT(BOOST_PP_CAT(has_member_function_callable_with_, BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME),_impl)
<Fun, true>
{
template<class U>
static BOOST_PP_CAT(zeroarg_checker_, BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME)
<U> Test(BOOST_PP_CAT(zeroarg_checker_, BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME)<U>*);
template <class U>
static boost_intrusive_has_member_function_callable_with::no_type Test(...);
static const bool value = sizeof(Test< Fun >(0))
== sizeof(boost_intrusive_has_member_function_callable_with::yes_type);
};
template<typename Fun, class ...DontCares>
struct BOOST_PP_CAT( funwrap_, BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME )
: Fun
{
BOOST_PP_CAT( funwrap_, BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME )();
using Fun::BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME;
boost_intrusive_has_member_function_callable_with::private_type
BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME
( DontCares...) const;
};
template<typename Fun, class ...Args>
struct BOOST_PP_CAT( BOOST_PP_CAT(has_member_function_callable_with_, BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME), _impl)
<Fun, true , Args...>
{
template<class T>
struct make_dontcare
{
typedef boost_intrusive_has_member_function_callable_with::dont_care type;
};
typedef BOOST_PP_CAT( funwrap_, BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME )
<Fun, typename make_dontcare<Args>::type...> FunWrap;
static bool const value = (sizeof(boost_intrusive_has_member_function_callable_with::no_type) ==
sizeof(boost_intrusive_has_member_function_callable_with::is_private_type
( (::boost::move_detail::declval< FunWrap >().
BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME
( ::boost::move_detail::declval<Args>()... ), 0) )
)
);
};
template<typename Fun, class ...Args>
struct BOOST_PP_CAT( has_member_function_callable_with_
, BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME)
: public BOOST_PP_CAT( BOOST_PP_CAT(has_member_function_callable_with_
, BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME),_impl)
< Fun
, BOOST_PP_CAT( has_member_function_named_
, BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME )<Fun>::value
, Args... >
{};
#endif //#if !defined(BOOST_INTRUSIVE_PERFECT_FORWARDING)
BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_END
#else //BOOST_PP_ITERATION() == 0
#if !defined(BOOST_INTRUSIVE_PERFECT_FORWARDING)
BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_BEGIN
template<typename Fun>
struct BOOST_PP_CAT( BOOST_PP_CAT(funwrap, BOOST_PP_ITERATION())
, BOOST_PP_CAT(_, BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME))
: Fun
{
BOOST_PP_CAT( BOOST_PP_CAT(funwrap, BOOST_PP_ITERATION())
, BOOST_PP_CAT(_, BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME))();
using Fun::BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME;
boost_intrusive_has_member_function_callable_with::private_type
BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME
( BOOST_PP_ENUM(BOOST_PP_ITERATION()
, BOOST_INTRUSIVE_PP_IDENTITY
, boost_intrusive_has_member_function_callable_with::dont_care)) const;
};
template<typename Fun BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PP_ITERATION(), class P)>
struct BOOST_PP_CAT( BOOST_PP_CAT(has_member_function_callable_with_
, BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME),_impl)
<Fun, true
BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PP_ITERATION(), P)
BOOST_PP_ENUM_TRAILING( BOOST_PP_SUB(BOOST_PP_ITERATION_FINISH(), BOOST_PP_ITERATION())
, BOOST_INTRUSIVE_PP_IDENTITY
, void)>
{
typedef BOOST_PP_CAT( BOOST_PP_CAT(funwrap, BOOST_PP_ITERATION())
, BOOST_PP_CAT(_, BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME))<Fun>
FunWrap;
static bool const value =
(sizeof(boost_intrusive_has_member_function_callable_with::no_type) ==
sizeof(boost_intrusive_has_member_function_callable_with::is_private_type
( (boost::move_detail::declval<FunWrap>().
BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME
( BOOST_PP_ENUM( BOOST_PP_ITERATION(), BOOST_INTRUSIVE_PP_DECLVAL, _) ), 0
)
)
)
);
};
BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_END
#endif //#if !defined(BOOST_INTRUSIVE_PERFECT_FORWARDING)
#endif //BOOST_PP_ITERATION() == 0
#if BOOST_PP_ITERATION() == BOOST_PP_ITERATION_FINISH()
#if !defined(BOOST_INTRUSIVE_PERFECT_FORWARDING)
BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_BEGIN
template<typename Fun
BOOST_PP_ENUM_TRAILING(BOOST_PP_ITERATION_FINISH(), BOOST_INTRUSIVE_PP_TEMPLATE_PARAM_VOID_DEFAULT, _)>
struct BOOST_PP_CAT(has_member_function_callable_with_, BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME)
: public BOOST_PP_CAT(BOOST_PP_CAT(has_member_function_callable_with_, BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME), _impl)
<Fun, BOOST_PP_CAT(has_member_function_named_, BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME)<Fun>::value
BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PP_ITERATION_FINISH(), P) >
{};
BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_END
#endif //#if !defined(BOOST_INTRUSIVE_PERFECT_FORWARDING)
#undef BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_FUNCNAME
#undef BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_BEGIN
#undef BOOST_INTRUSIVE_HAS_MEMBER_FUNCTION_CALLABLE_WITH_NS_END
#endif //#if BOOST_PP_ITERATION() == BOOST_PP_ITERATION_FINISH()
#endif //!BOOST_PP_IS_ITERATING