variant
A type safe generalized union type
visitor.hpp
Go to the documentation of this file.
1 /*
2  * Boost Software License - Version 1.0 - August 17th, 2003
3  *
4  * Permission is hereby granted, free of charge, to any person or organization
5  * obtaining a copy of the software and accompanying documentation covered by
6  * this license (the "Software") to use, reproduce, display, distribute,
7  * execute, and transmit the Software, and to prepare derivative works of the
8  * Software, and to permit third-parties to whom the Software is furnished to
9  * do so, all subject to the following:
10  *
11  * The copyright notices in the Software and this entire statement, including
12  * the above license grant, this restriction and the following disclaimer,
13  * must be included in all copies of the Software, in whole or in part, and
14  * all derivative works of the Software, unless such copies or derivative
15  * works are solely in the form of machine-executable object code generated by
16  * a source language processor.
17  *
18  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20  * FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
21  * SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
22  * FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
23  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
24  * DEALINGS IN THE SOFTWARE.
25  *
26  */
27 
28 #ifndef VISITOR_HPP
29 #define VISITOR_HPP
30 
38 #include <utility>
39 #include <type_traits>
40 
41 #include "variant_storage.hpp"
42 
43 template<class ... Types>
44 class variant;
45 
46 template<class Callable, class T>
47 class curried_t
48 {
49 public:
50  curried_t( Callable && f, T && value )
51  noexcept( detail::and_<
52  std::is_nothrow_constructible<Callable, Callable &&>,
53  std::is_nothrow_constructible<T, T&&> >::value ) :
54  f( std::forward<Callable>(f) ),
55  value( std::forward<T>(value) )
56  {}
57 
58  template<class ... Args>
59  std::result_of_t< Callable&( T&, Args&& ... )> operator()(Args && ... args) &
60  noexcept(
61  noexcept( std::declval<Callable&>() ( std::declval<T&>(), std::declval<Args&&>() ... )
62  )
63  )
64  {
65  return std::forward<Callable&>(f)( std::forward<T&>(value), std::forward<Args>(args) ... );
66  }
67 
68  template<class ... Args>
69  std::result_of_t< Callable&&( T&&, Args&& ... )> operator()(Args && ... args) &&
70  noexcept(
71  noexcept( std::declval<Callable&&>() ( std::declval<T&&>(), std::declval<Args&&>() ... )
72  )
73  )
74  {
75  return std::forward<Callable&&>(f)( std::forward<T&&>(value), std::forward<Args>(args) ... );
76  }
77 
78  template<class ... Args>
79  std::result_of_t< Callable&( T&, Args&& ... )> operator()(Args && ... args) const &
80  noexcept(
81  noexcept( std::declval<Callable const &>() ( std::declval<T const &>(), std::declval<Args&&>() ... )
82  )
83  )
84  {
85  return std::forward<Callable const &>(f)( std::forward<T const &>(value), std::forward<Args>(args) ... );
86  }
87 
88 private:
89  Callable f;
90  T value;
91 };
92 
96 template<class Callable, class ... Args>
98 
99 template<class Callable, class ... Args>
100 using result_of_visit_t = typename result_of_visit<Callable, Args ...>::type;
101 
105 template<class Callable, class ... Args>
107 
108 #ifndef VARIANT_IN_DOXYGEN_PARSING
109 
110 template<class Callable>
111 struct result_of_visit<Callable>
112 {
113  typedef std::result_of_t< Callable() > type;
114 };
115 
116 template<class Callable, class ... Args, class ... Tail>
117 struct result_of_visit< Callable, variant<Args...> &, Tail ... >
118 {
119  typedef std::common_type_t<
120  typename result_of_visit< Callable, Args&, Tail ... >::type ...
121  > type;
122 };
123 
124 template<class Callable, class ... Args, class ... Tail>
125 struct result_of_visit< Callable, variant<Args...> &&, Tail ... >
126 {
127  typedef std::common_type_t<
128  typename result_of_visit< Callable, Args&&, Tail ... >::type ...
129  > type;
130 };
131 
132 template<class Callable, class ... Args, class ... Tail>
133 struct result_of_visit< Callable, variant<Args...> const &, Tail ... >
134 {
135  typedef std::common_type_t<
136  typename result_of_visit< Callable, Args const &, Tail ... >::type ...
137  > type;
138 };
139 
140 template<class Callable, class Head, class ... Tail>
141 struct result_of_visit< Callable, Head, Tail ... > :
142  result_of_visit< curried_t<Callable, Head>, Tail ... > {};
143 
144 
145 template<class Callable>
146 struct is_nothrow_visitable<Callable> :
147  std::integral_constant<
148  bool,
149  noexcept( std::declval<Callable>()() )
150  > {};
151 
152 template<class Callable, class Head, class ... Tail>
153 struct is_nothrow_visitable<Callable, Head, Tail ... > :
154  is_nothrow_visitable< curried_t<Callable, Head>, Tail ... > {};
155 
156 template<class Callable, class ... Args, class ... Tail>
157 struct is_nothrow_visitable<Callable, variant<Args... > &, Tail ... > :
158  detail::and_<
160  Callable,
161  Args&,
162  Tail ... > ... > {};
163 
164 template<class Callable, class ... Args, class ... Tail>
165 struct is_nothrow_visitable<Callable, variant<Args... > &&, Tail ...> :
166  detail::and_<
168  Callable,
169  Args&&,
170  Tail ... > ... > {};
171 
172 template<class Callable, class ... Args, class ... Tail>
173 struct is_nothrow_visitable<Callable, variant<Args... > const &, Tail ...> :
174  detail::and_<
176  Callable,
177  Args const &,
178  Tail ... > ... > {};
179 
180 #endif //VARIANT_IN_DOXYGEN_PARSING
181 
195 template<class Callable, class ... Args>
196 result_of_visit_t<Callable&&, Args&& ...> apply_visitor(Callable && c, Args && ... args)
197  noexcept( is_nothrow_visitable<Callable &&, Args && ...>::value );
198 
199 template<class Callable>
200 result_of_visit_t<Callable&&> apply_visitor(Callable && c)
201  noexcept( is_nothrow_visitable<Callable&&>::value )
202 {
203  return std::forward<Callable>(c)();
204 }
205 
206 template<class Callable, class Head, class ... Tail>
207 result_of_visit_t<Callable&&, Head&&, Tail&& ...> apply_visitor(Callable && c, Head && head, Tail && ... tail)
208  noexcept( is_nothrow_visitable<Callable &&, Head &&, Tail && ...>::value )
209 {
210  return apply_visitor(
211  [&](auto && ... args)
212  {
213  return std::forward<Callable>(c)( std::forward<Head>(head), std::forward<decltype(args)>(args) ... );
214  },
215  std::forward<Tail>(tail) ... );
216 }
217 
218 template<class Callable, class ... Args, class ... Tail>
219 result_of_visit_t<Callable&&, variant<Args...> &, Tail&& ...> apply_visitor(Callable && c, variant<Args...> & head, Tail && ... tail)
220  noexcept( is_nothrow_visitable<Callable&&, variant<Args...> &, Tail && ... >::value )
221 {
222  return invoke(
223  [&](auto & val)
224  {
225  return apply_visitor( std::forward<Callable>(c), val, std::forward<Tail>(tail) ... );
226  },
227  head.get_storage(),
228  head.which() );
229 }
230 
231 template<class Callable, class ... Args, class ... Tail>
232 result_of_visit_t<Callable&&, variant<Args...> &&, Tail && ...> apply_visitor(Callable && c, variant<Args...> && head, Tail && ... tail)
233  noexcept( is_nothrow_visitable<Callable&&, variant<Args...> &&, Tail && ...>::value )
234 {
235  return invoke(
236  [&](auto && val)
237  {
238  return apply_visitor( std::forward<Callable>(c), std::move(val), std::forward<Tail>(tail) ... );
239  },
240  std::move(head).get_storage(),
241  head.which() );
242 }
243 
244 template<class Callable, class ... Args, class ... Tail>
245 result_of_visit_t<Callable&&, variant<Args...> const &, Tail && ...> apply_visitor(Callable && c, variant<Args...> const & head, Tail && ... tail)
246  noexcept( is_nothrow_visitable<Callable&&, variant<Args...> const &, Tail && ... >::value )
247 {
248  return invoke(
249  [&](auto & val)
250  {
251  return apply_visitor( std::forward<Callable>(c), val, std::forward<Tail>(tail) ... );
252  },
253  head.get_storage(),
254  head.which() );
255 }
256 
257 #endif // VISITOR_HPP
Implements the class variant_storage.
result_of_visit_t< Callable &&, Args &&...> apply_visitor(Callable &&c, Args &&...args) noexcept(is_nothrow_visitable< Callable &&, Args &&...>::value)
Calls the provided Callable with the given Args, replacing the variant args with the actual type...
Determine if a visit operation might throw.
Definition: visitor.hpp:106
std::size_t which() const noexcept
Return the index of the current bound object.
Definition: variant.hpp:566
Definition: relational.hpp:33
A type safe generalized union.
Definition: variant.hpp:65
Compute the result type of a visit.
Definition: visitor.hpp:97
decltype(auto) invoke(Callable &&c, VariantStorage &&v, std::size_t which) noexcept(noexcept(invoke_variant_storage_t{}(std::forward< Callable >(c), std::forward< VariantStorage >(v), which)))
Calls the provided Callable with an element of the supplied variant storage.
Definition: variant_storage.hpp:386