Bond
 
Loading...
Searching...
No Matches
visit_any.h
1// Copyright (c) Microsoft. All rights reserved.
2// Licensed under the MIT license. See LICENSE file in the project root for full license information.
3
4#pragma once
5
6#include <bond/core/config.h>
7
8#include "mpl.h"
9
10#include <boost/optional.hpp>
11
12#include <type_traits>
13
14namespace bond
15{
16
17namespace detail
18{
19
20#if !defined(BOND_NO_CXX14_RETURN_TYPE_DEDUCTION) && !defined(BOND_NO_CXX14_GENERIC_LAMBDAS)
21
22#if defined(BOND_CXX_17)
23 template<typename Visitor, typename T>
24 using invoke_result_of_t = std::invoke_result_t<Visitor, T&>;
25#else
26 template<typename Visitor, typename T>
27 using invoke_result_of_t = std::result_of_t<Visitor(T&)>;
28#endif
29
30template <typename T, typename Visitor, typename Any>
31inline typename boost::disable_if<std::is_void<invoke_result_of_t<Visitor, T> >, boost::optional<invoke_result_of_t<Visitor, T> > >::type
32try_visit_any(Visitor&& visitor, Any& x)
33{
34 if (auto value = any_cast<T>(&x))
35 {
36 return std::forward<Visitor>(visitor)(*value);
37 }
38
39 return {};
40}
41
42template <typename T, typename Visitor, typename Any>
43inline typename boost::enable_if<std::is_void<invoke_result_of_t<Visitor, T> >, bool>::type
44try_visit_any(Visitor&& visitor, Any& x)
45{
46 if (auto value = any_cast<T>(&x))
47 {
48 std::forward<Visitor>(visitor)(*value);
49 return true;
50 }
51
52 return false;
53}
54
55template <typename List, typename Visitor, typename Any>
56inline auto visit_any(Visitor&& visitor, Any& x)
57{
58 return mpl::try_apply<List>(
59 [&](auto identity)
60 {
61 (void)identity;
62 return try_visit_any<typename decltype(identity)::type>(std::forward<Visitor>(visitor), x);
63 });
64}
65
66#else
67
68template <typename Result, typename Visitor, typename Any>
69struct try_visit_any
70{
71 try_visit_any(Visitor& visitor, Any& x)
72 : _visitor(visitor),
73 _x(x)
74 {}
75
76 try_visit_any& operator=(const try_visit_any& other) = delete;
77
78 template <typename T, typename R = Result>
79 typename boost::disable_if<std::is_void<R>, boost::optional<Result> >::type
80 operator()(const mpl::identity<T>&) const
81 {
82 if (auto value = any_cast<T>(&_x))
83 {
84 return _visitor(*value);
85 }
86
87 return {};
88 }
89
90 template <typename T, typename R = Result>
91 typename boost::enable_if<std::is_void<R>, bool>::type
92 operator()(const mpl::identity<T>&) const
93 {
94 if (auto value = any_cast<T>(&_x))
95 {
96 _visitor(*value);
97 return true;
98 }
99
100 return false;
101 }
102
103 Visitor& _visitor;
104 Any& _x;
105};
106
107template <typename T> struct
108visitor_result
109{
110 using type = boost::optional<T>;
111};
112
113template <> struct
114visitor_result<void>
115{
116 using type = bool;
117};
118
119template <typename Result, typename Visitor, typename Any, typename T, typename... U>
120inline typename visitor_result<Result>::type visit_any(Visitor&& visitor, Any& x, const mpl::list<T, U...>&)
121{
122 return mpl::try_apply<mpl::list<T, U...> >(try_visit_any<Result, Visitor, Any>(visitor, x));
123}
124
125template <typename List, typename Result, typename Visitor, typename Any>
126inline typename visitor_result<Result>::type visit_any(Visitor&& visitor, Any& x)
127{
128 return visit_any<Result>(std::forward<Visitor>(visitor), x, List{});
129}
130
131#endif
132
133
134} // namespace detail
135
136} // namespace bond
namespace bond
Definition: apply.h:17