boost/multi_index/detail/is_transparent.hpp
/* Copyright 2003-2014 Joaquin M Lopez Munoz.
* 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/multi_index for library home page.
*/
#ifndef BOOST_MULTI_INDEX_DETAIL_IS_TRANSPARENT_HPP
#define BOOST_MULTI_INDEX_DETAIL_IS_TRANSPARENT_HPP
#if defined(_MSC_VER)
#pragma once
#endif
#include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
#include <boost/mpl/bool.hpp>
#include <boost/type_traits/intrinsics.hpp>
namespace boost{
namespace multi_index{
namespace detail{
/* Metafunction that checks if f(arg,arg2) executes without argument type
* conversion. By default (i.e. when it cannot be determined) it evaluates to
* true.
*/
template<typename F,typename Arg1,typename Arg2,typename=void>
struct is_transparent:mpl::true_{};
} /* namespace multi_index::detail */
} /* namespace multi_index */
} /* namespace boost */
#if !defined(BOOST_NO_SFINAE)&&!defined(BOOST_NO_SFINAE_EXPR)&& \
!defined(BOOST_NO_CXX11_DECLTYPE)&& \
(defined(BOOST_NO_CXX11_FINAL)||defined(BOOST_IS_FINAL))
#include <boost/mpl/and.hpp>
#include <boost/mpl/not.hpp>
#include <boost/mpl/or.hpp>
#include <boost/type_traits/function_traits.hpp>
#include <boost/type_traits/is_class.hpp>
#include <boost/type_traits/is_final.hpp>
#include <boost/type_traits/is_function.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/type_traits/remove_pointer.hpp>
#include <boost/utility/declval.hpp>
#include <boost/utility/enable_if.hpp>
namespace boost{
namespace multi_index{
namespace detail{
struct not_is_transparent_result_type{};
template<typename F,typename Arg1,typename Arg2>
struct is_transparent_class_helper:F
{
using F::operator();
template<typename T,typename Q>
not_is_transparent_result_type operator()(const T&,const Q&)const;
};
template<typename F,typename Arg1,typename Arg2,typename=void>
struct is_transparent_class:mpl::true_{};
template<typename F,typename Arg1,typename Arg2>
struct is_transparent_class<
F,Arg1,Arg2,
typename enable_if<
is_same<
decltype(
declval<const is_transparent_class_helper<F,Arg1,Arg2> >()(
declval<const Arg1&>(),declval<const Arg2&>())
),
not_is_transparent_result_type
>
>::type
>:mpl::false_{};
template<typename F,typename Arg1,typename Arg2>
struct is_transparent<
F,Arg1,Arg2,
typename enable_if<
mpl::and_<
is_class<F>,
mpl::not_<is_final<F> > /* is_transparent_class_helper derives from F */
>
>::type
>:is_transparent_class<F,Arg1,Arg2>{};
template<typename F,typename Arg1,typename Arg2,typename=void>
struct is_transparent_function:mpl::true_{};
template<typename F,typename Arg1,typename Arg2>
struct is_transparent_function<
F,Arg1,Arg2,
typename enable_if<
mpl::or_<
mpl::not_<mpl::or_<
is_same<typename function_traits<F>::arg1_type,const Arg1&>,
is_same<typename function_traits<F>::arg1_type,Arg1>
> >,
mpl::not_<mpl::or_<
is_same<typename function_traits<F>::arg2_type,const Arg2&>,
is_same<typename function_traits<F>::arg2_type,Arg2>
> >
>
>::type
>:mpl::false_{};
template<typename F,typename Arg1,typename Arg2>
struct is_transparent<
F,Arg1,Arg2,
typename enable_if<
is_function<typename remove_pointer<F>::type>
>::type
>:is_transparent_function<typename remove_pointer<F>::type,Arg1,Arg2>{};
} /* namespace multi_index::detail */
} /* namespace multi_index */
} /* namespace boost */
#endif
#endif