• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2 
3 @Copyright Barrett Adair 2015-2017
4 Distributed under the Boost Software License, Version 1.0.
5 (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
6 
7 */
8 
9 #ifndef BOOST_CLBL_TRTS_APPLY_MEMBER_POINTER_HPP
10 #define BOOST_CLBL_TRTS_APPLY_MEMBER_POINTER_HPP
11 
12 #include <boost/callable_traits/detail/core.hpp>
13 
14 namespace boost { namespace callable_traits {
15 
16 BOOST_CLBL_TRTS_DEFINE_SFINAE_ERROR_ORIGIN(apply_member_pointer)
17 BOOST_CLBL_TRTS_SFINAE_MSG(apply_member_pointer, members_cannot_have_a_type_of_void)
18 BOOST_CLBL_TRTS_SFINAE_MSG(apply_member_pointer, second_template_argument_must_be_a_class_or_struct)
19 
20 namespace detail {
21 
22     template<typename T, typename C, bool = std::is_class<C>::value>
23     struct make_member_pointer;
24 
25     template<typename T, typename C>
26     struct make_member_pointer<T, C, true> {
27         using type = typename std::remove_reference<T>::type C::*;
28     };
29 
30     template<typename C>
31     struct make_member_pointer<void, C, true> {
32         using type = invalid_type;
33     };
34 
35     template<typename T, typename C>
36     struct make_member_pointer<T, C, false> {
37         using type = error_type<T>;
38     };
39 
40     template<typename T, typename C>
41     using make_member_pointer_t = typename make_member_pointer<T, C>::type;
42 }
43 
44 //[ apply_member_pointer_hpp
45 /*`
46 [section:ref_apply_member_pointer apply_member_pointer]
47 [heading Header]
48 ``#include <boost/callable_traits/apply_member_pointer.hpp>``
49 [heading Definition]
50 */
51 
52 template<typename T, typename C>
53 using apply_member_pointer_t = //see below
54 //<-
55     detail::sfinae_try<
56         detail::fallback_if_invalid<
57             typename detail::traits<T>::template apply_member_pointer<C>,
58             typename detail::make_member_pointer<T, C>::type>,
59 
60         detail::fail_when_same<void, T, members_cannot_have_a_type_of_void>,
61 
62         detail::fail_if<!std::is_class<C>::value,
63             second_template_argument_must_be_a_class_or_struct> >;
64 
65 namespace detail {
66 
67     template<typename T, typename C, typename = std::false_type>
68     struct apply_member_pointer_impl {};
69 
70     template<typename T, typename C>
71     struct apply_member_pointer_impl <T, C, typename std::is_same<
72         apply_member_pointer_t<T, C>, detail::dummy>::type>
73     {
74         using type = apply_member_pointer_t<T, C>;
75     };
76 }
77 
78 //->
79 
80 template<typename T, typename C>
81 struct apply_member_pointer : detail::apply_member_pointer_impl<T, C> {};
82 
83 //<-
84 }} // namespace boost::callable_traits
85 //->
86 
87 /*`
88 [heading Constraints]
89 * `T` may be any type except `void`
90 * `C` must be a user-defined type
91 
92 [heading Behavior]
93 * A substitution failure occurs if the constraints are violated.
94 * When `T` is a function, function pointer (unqualified), or function reference, then the aliased type is a member function pointer of `C` with the same parameters and return type.
95 * When `T` is a member function pointer (unqualified)  of any type, the aliased type is a member function pointer of `C` with the same parameters and return type.
96 * Otherwise, the aliased type is a member data pointer equivalent to `std::remove_reference_t<T> C::*`.
97 
98 [heading Input/Output Examples]
99 [table
100     [[`T`]                              [`apply_member_pointer_t<T, foo>`]]
101     [[`int()`]                          [`int(foo::*)()`]]
102     [[`int (&)()`]                      [`int(foo::*)()`]]
103     [[`int (*)()`]                      [`int(foo::*)()`]]
104     [[`int(bar::*)()`]                  [`int(foo::*)()`]]
105     [[`int(bar::*)() &`]                [`int(foo::*)() &`]]
106     [[`int(bar::*)() &&`]               [`int(foo::*)() &&`]]
107     [[`int(bar::*)() const`]            [`int(foo::*)() const`]]
108     [[`int(bar::*)() transaction_safe`] [`int(foo::*)() transaction_safe`]]
109     [[`int bar::*`]                     [`int foo::*`]]
110     [[`int`]                            [`int foo::*`]]
111     [[`int &`]                          [`int foo::*`]]
112     [[`const int &`]                    [`const int foo::*`]]
113     [[`int (*const)()`]                 [`int (*const foo::*)()`]]
114     [[`void`]                           [(substitution failure)]]
115 ]
116 
117 [heading Example Program]
118 [import ../example/apply_member_pointer.cpp]
119 [apply_member_pointer]
120 [endsect]
121 */
122 //]
123 #endif
124