]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | // boost utility/base_from_member.hpp header file --------------------------// |
2 | ||
3 | // Copyright 2001, 2003, 2004, 2012 Daryle Walker. Use, modification, and | |
4 | // distribution are subject to the Boost Software License, Version 1.0. (See | |
5 | // accompanying file LICENSE_1_0.txt or a copy at | |
6 | // <http://www.boost.org/LICENSE_1_0.txt>.) | |
7 | ||
8 | // See <http://www.boost.org/libs/utility/> for the library's home page. | |
9 | ||
10 | #ifndef BOOST_UTILITY_BASE_FROM_MEMBER_HPP | |
11 | #define BOOST_UTILITY_BASE_FROM_MEMBER_HPP | |
12 | ||
13 | #include <boost/config.hpp> | |
14 | #include <boost/preprocessor/arithmetic/inc.hpp> | |
15 | #include <boost/preprocessor/repetition/enum_binary_params.hpp> | |
16 | #include <boost/preprocessor/repetition/enum_params.hpp> | |
17 | #include <boost/preprocessor/repetition/repeat_from_to.hpp> | |
18 | #include <boost/type_traits/is_same.hpp> | |
19 | #include <boost/type_traits/remove_cv.hpp> | |
20 | #include <boost/type_traits/remove_reference.hpp> | |
21 | #include <boost/utility/enable_if.hpp> | |
22 | ||
23 | ||
24 | // Base-from-member arity configuration macro ------------------------------// | |
25 | ||
26 | // The following macro determines how many arguments will be in the largest | |
27 | // constructor template of base_from_member. Constructor templates will be | |
28 | // generated from one argument to this maximum. Code from other files can read | |
29 | // this number if they need to always match the exact maximum base_from_member | |
30 | // uses. The maximum constructor length can be changed by overriding the | |
31 | // #defined constant. Make sure to apply the override, if any, for all source | |
32 | // files during project compiling for consistency. | |
33 | ||
34 | // Contributed by Jonathan Turkanis | |
35 | ||
36 | #ifndef BOOST_BASE_FROM_MEMBER_MAX_ARITY | |
37 | #define BOOST_BASE_FROM_MEMBER_MAX_ARITY 10 | |
38 | #endif | |
39 | ||
40 | ||
41 | // An iteration of a constructor template for base_from_member -------------// | |
42 | ||
43 | // A macro that should expand to: | |
44 | // template < typename T1, ..., typename Tn > | |
45 | // base_from_member( T1 x1, ..., Tn xn ) | |
46 | // : member( x1, ..., xn ) | |
47 | // {} | |
48 | // This macro should only persist within this file. | |
49 | ||
50 | #define BOOST_PRIVATE_CTR_DEF( z, n, data ) \ | |
51 | template < BOOST_PP_ENUM_PARAMS(n, typename T) > \ | |
52 | base_from_member( BOOST_PP_ENUM_BINARY_PARAMS(n, T, x) ) \ | |
53 | : member( BOOST_PP_ENUM_PARAMS(n, x) ) \ | |
54 | {} \ | |
55 | /**/ | |
56 | ||
57 | ||
58 | namespace boost | |
59 | { | |
60 | ||
61 | namespace detail | |
62 | { | |
63 | ||
64 | // Type-unmarking class template -------------------------------------------// | |
65 | ||
66 | // Type-trait to get the raw type, i.e. the type without top-level reference nor | |
67 | // cv-qualification, from a type expression. Mainly for function arguments, any | |
68 | // reference part is stripped first. | |
69 | ||
70 | // Contributed by Daryle Walker | |
71 | ||
72 | template < typename T > | |
73 | struct remove_cv_ref | |
74 | { | |
75 | typedef typename ::boost::remove_cv<typename | |
76 | ::boost::remove_reference<T>::type>::type type; | |
77 | ||
78 | }; // boost::detail::remove_cv_ref | |
79 | ||
80 | // Unmarked-type comparison class template ---------------------------------// | |
81 | ||
82 | // Type-trait to check if two type expressions have the same raw type. | |
83 | ||
84 | // Contributed by Daryle Walker, based on a work-around by Luc Danton | |
85 | ||
86 | template < typename T, typename U > | |
87 | struct is_related | |
88 | : public ::boost::is_same< | |
89 | typename ::boost::detail::remove_cv_ref<T>::type, | |
90 | typename ::boost::detail::remove_cv_ref<U>::type > | |
91 | {}; | |
92 | ||
93 | // Enable-if-on-unidentical-unmarked-type class template -------------------// | |
94 | ||
95 | // Enable-if on the first two type expressions NOT having the same raw type. | |
96 | ||
97 | // Contributed by Daryle Walker, based on a work-around by Luc Danton | |
98 | ||
99 | #ifndef BOOST_NO_CXX11_VARIADIC_TEMPLATES | |
100 | template<typename ...T> | |
101 | struct enable_if_unrelated | |
102 | : public ::boost::enable_if_c<true> | |
103 | {}; | |
104 | ||
105 | template<typename T, typename U, typename ...U2> | |
106 | struct enable_if_unrelated<T, U, U2...> | |
107 | : public ::boost::disable_if< ::boost::detail::is_related<T, U> > | |
108 | {}; | |
109 | #endif | |
110 | ||
111 | } // namespace boost::detail | |
112 | ||
113 | ||
114 | // Base-from-member class template -----------------------------------------// | |
115 | ||
116 | // Helper to initialize a base object so a derived class can use this | |
117 | // object in the initialization of another base class. Used by | |
118 | // Dietmar Kuehl from ideas by Ron Klatcho to solve the problem of a | |
119 | // base class needing to be initialized by a member. | |
120 | ||
121 | // Contributed by Daryle Walker | |
122 | ||
123 | template < typename MemberType, int UniqueID = 0 > | |
124 | class base_from_member | |
125 | { | |
126 | protected: | |
127 | MemberType member; | |
128 | ||
129 | #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && \ | |
130 | !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && \ | |
131 | !defined(BOOST_NO_CXX11_FUNCTION_TEMPLATE_DEFAULT_ARGS) && \ | |
132 | !(defined(__GNUC__) && (__GNUC__ == 4) && (__GNUC_MINOR__ < 4)) | |
133 | template <typename ...T, typename EnableIf = typename | |
134 | ::boost::detail::enable_if_unrelated<base_from_member, T...>::type> | |
135 | explicit BOOST_CONSTEXPR base_from_member( T&& ...x ) | |
136 | BOOST_NOEXCEPT_IF( BOOST_NOEXCEPT_EXPR(::new ((void*) 0) MemberType( | |
137 | static_cast<T&&>(x)... )) ) // no std::is_nothrow_constructible... | |
138 | : member( static_cast<T&&>(x)... ) // ...nor std::forward needed | |
139 | {} | |
140 | #else | |
141 | base_from_member() | |
142 | : member() | |
143 | {} | |
144 | ||
145 | template < typename T0 > explicit base_from_member( T0 x0 ) : member( x0 ) {} | |
146 | BOOST_PP_REPEAT_FROM_TO( 2, BOOST_PP_INC(BOOST_BASE_FROM_MEMBER_MAX_ARITY), | |
147 | BOOST_PRIVATE_CTR_DEF, _ ) | |
148 | #endif | |
149 | ||
150 | }; // boost::base_from_member | |
151 | ||
152 | template < typename MemberType, int UniqueID > | |
153 | class base_from_member<MemberType&, UniqueID> | |
154 | { | |
155 | protected: | |
156 | MemberType& member; | |
157 | ||
158 | explicit BOOST_CONSTEXPR base_from_member( MemberType& x ) | |
159 | BOOST_NOEXCEPT | |
160 | : member( x ) | |
161 | {} | |
162 | ||
163 | }; // boost::base_from_member | |
164 | ||
165 | } // namespace boost | |
166 | ||
167 | ||
168 | // Undo any private macros | |
169 | #undef BOOST_PRIVATE_CTR_DEF | |
170 | ||
171 | ||
172 | #endif // BOOST_UTILITY_BASE_FROM_MEMBER_HPP |