1 /* Copyright 2003-2014 Joaquin M Lopez Munoz.
2  * Distributed under the Boost Software License, Version 1.0.
3  * (See accompanying file LICENSE_1_0.txt or copy at
4  * http://www.boost.org/LICENSE_1_0.txt)
5  *
6  * See http://www.boost.org/libs/multi_index for library home page.
7  */
8 
9 #ifndef BOOST_MULTI_INDEX_DETAIL_IS_TRANSPARENT_HPP
10 #define BOOST_MULTI_INDEX_DETAIL_IS_TRANSPARENT_HPP
11 
12 #if defined(_MSC_VER)
13 #pragma once
14 #endif
15 
16 #include <boost/config.hpp> /* keep it first to prevent nasty warns in MSVC */
17 #include <boost/mpl/bool.hpp>
18 #include <boost/type_traits/intrinsics.hpp>
19 
20 namespace boost{
21 
22 namespace multi_index{
23 
24 namespace detail{
25 
26 /* Metafunction that checks if f(arg,arg2) executes without argument type
27  * conversion. By default (i.e. when it cannot be determined) it evaluates to
28  * true.
29  */
30 
31 template<typename F,typename Arg1,typename Arg2,typename=void>
32 struct is_transparent:mpl::true_{};
33 
34 } /* namespace multi_index::detail */
35 
36 } /* namespace multi_index */
37 
38 } /* namespace boost */
39 
40 #if !defined(BOOST_NO_SFINAE)&&!defined(BOOST_NO_SFINAE_EXPR)&& \
41     !defined(BOOST_NO_CXX11_DECLTYPE)&& \
42     (defined(BOOST_NO_CXX11_FINAL)||defined(BOOST_IS_FINAL))
43 
44 #include <boost/mpl/and.hpp>
45 #include <boost/mpl/not.hpp>
46 #include <boost/mpl/or.hpp>
47 #include <boost/type_traits/function_traits.hpp>
48 #include <boost/type_traits/is_class.hpp>
49 #include <boost/type_traits/is_final.hpp>
50 #include <boost/type_traits/is_function.hpp>
51 #include <boost/type_traits/is_same.hpp>
52 #include <boost/type_traits/remove_pointer.hpp>
53 #include <boost/utility/declval.hpp>
54 #include <boost/utility/enable_if.hpp>
55 
56 namespace boost{
57 
58 namespace multi_index{
59 
60 namespace detail{
61 
62 struct not_is_transparent_result_type{};
63 
64 template<typename F,typename Arg1,typename Arg2>
65 struct is_transparent_class_helper:F
66 {
67   using F::operator();
68   template<typename T,typename Q>
69   not_is_transparent_result_type operator()(const T&,const Q&)const;
70 };
71 
72 template<typename F,typename Arg1,typename Arg2,typename=void>
73 struct is_transparent_class:mpl::true_{};
74 
75 template<typename F,typename Arg1,typename Arg2>
76 struct is_transparent_class<
77   F,Arg1,Arg2,
78   typename enable_if<
79     is_same<
80       decltype(
81         declval<const is_transparent_class_helper<F,Arg1,Arg2> >()(
82           declval<const Arg1&>(),declval<const Arg2&>())
83       ),
84       not_is_transparent_result_type
85     >
86   >::type
87 >:mpl::false_{};
88 
89 template<typename F,typename Arg1,typename Arg2>
90 struct is_transparent<
91   F,Arg1,Arg2,
92   typename enable_if<
93     mpl::and_<
94       is_class<F>,
95       mpl::not_<is_final<F> > /* is_transparent_class_helper derives from F */
96     >
97   >::type
98 >:is_transparent_class<F,Arg1,Arg2>{};
99 
100 template<typename F,typename Arg1,typename Arg2,typename=void>
101 struct is_transparent_function:mpl::true_{};
102 
103 template<typename F,typename Arg1,typename Arg2>
104 struct is_transparent_function<
105   F,Arg1,Arg2,
106   typename enable_if<
107     mpl::or_<
108       mpl::not_<mpl::or_<
109         is_same<typename function_traits<F>::arg1_type,const Arg1&>,
110         is_same<typename function_traits<F>::arg1_type,Arg1>
111       > >,
112       mpl::not_<mpl::or_<
113         is_same<typename function_traits<F>::arg2_type,const Arg2&>,
114         is_same<typename function_traits<F>::arg2_type,Arg2>
115       > >
116     >
117   >::type
118 >:mpl::false_{};
119 
120 template<typename F,typename Arg1,typename Arg2>
121 struct is_transparent<
122   F,Arg1,Arg2,
123   typename enable_if<
124     is_function<typename remove_pointer<F>::type>
125   >::type
126 >:is_transparent_function<typename remove_pointer<F>::type,Arg1,Arg2>{};
127 
128 } /* namespace multi_index::detail */
129 
130 } /* namespace multi_index */
131 
132 } /* namespace boost */
133 
134 #endif
135 #endif
136