1 //-----------------------------------------------------------------------------
2 // boost variant/visitor_ptr.hpp header file
3 // See http://www.boost.org for updates, documentation, and revision history.
4 //-----------------------------------------------------------------------------
5 //
6 // Copyright (c) 2002-2003
7 // Eric Friedman
8 //
9 // Distributed under the Boost Software License, Version 1.0. (See
10 // accompanying file LICENSE_1_0.txt or copy at
11 // http://www.boost.org/LICENSE_1_0.txt)
12 
13 #ifndef BOOST_VARIANT_VISITOR_PTR_HPP
14 #define BOOST_VARIANT_VISITOR_PTR_HPP
15 
16 #include <boost/variant/bad_visit.hpp>
17 #include <boost/variant/static_visitor.hpp>
18 
19 #include <boost/mpl/eval_if.hpp>
20 #include <boost/mpl/identity.hpp>
21 #include <boost/throw_exception.hpp>
22 #include <boost/type_traits/add_reference.hpp>
23 #include <boost/type_traits/is_reference.hpp>
24 #include <boost/type_traits/is_void.hpp>
25 
26 namespace boost {
27 
28 //////////////////////////////////////////////////////////////////////////
29 // function template visitor_ptr
30 //
31 // Adapts a function pointer for use as visitor capable of handling
32 // values of a single type. Throws bad_visit if inappropriately applied.
33 //
34 template <typename T, typename R>
35 class visitor_ptr_t
36     : public static_visitor<R>
37 {
38 private: // representation
39 
40     typedef R (*visitor_t)(T);
41 
42     visitor_t visitor_;
43 
44 public: // typedefs
45 
46     typedef R result_type;
47 
48 private: // private typedefs
49 
50     typedef typename mpl::eval_if<
51           is_reference<T>
52         , mpl::identity<T>
53         , add_reference<const T>
54         >::type argument_fwd_type;
55 
56 public: // structors
57 
visitor_ptr_t(visitor_t visitor)58     explicit visitor_ptr_t(visitor_t visitor) BOOST_NOEXCEPT
59       : visitor_(visitor)
60     {
61     }
62 
63 public: // static visitor interfaces
64 
65     template <typename U>
operator ()(const U &) const66     result_type operator()(const U&) const
67     {
68         boost::throw_exception(bad_visit());
69     }
70 
71 #if !defined(BOOST_NO_VOID_RETURNS)
72 
73 public: // static visitor interfaces, cont.
74 
operator ()(argument_fwd_type operand) const75     result_type operator()(argument_fwd_type operand) const
76     {
77         return visitor_(operand);
78     }
79 
80 #else // defined(BOOST_NO_VOID_RETURNS)
81 
82 private: // helpers, for static visitor interfaces (below)
83 
execute_impl(argument_fwd_type operand,mpl::false_) const84     result_type execute_impl(argument_fwd_type operand, mpl::false_) const
85     {
86         return visitor_(operand);
87     }
88 
89         BOOST_VARIANT_AUX_RETURN_VOID_TYPE
execute_impl(argument_fwd_type operand,mpl::true_) const90     execute_impl(argument_fwd_type operand, mpl::true_) const
91     {
92         visitor_(operand);
93         BOOST_VARIANT_AUX_RETURN_VOID;
94     }
95 
96 public: // static visitor interfaces, cont.
97 
BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(result_type)98         BOOST_VARIANT_AUX_GENERIC_RESULT_TYPE(result_type)
99     operator()(argument_fwd_type operand) const
100     {
101         typedef typename is_void<result_type>::type has_void_result;
102         return execute_impl(operand, has_void_result());
103     }
104 
105 #endif // BOOST_NO_VOID_RETURNS workaround
106 
107 };
108 
109 template <typename R, typename T>
visitor_ptr(R (* visitor)(T))110 inline visitor_ptr_t<T,R> visitor_ptr(R (*visitor)(T))
111 {
112     return visitor_ptr_t<T,R>(visitor);
113 }
114 
115 } // namespace boost
116 
117 #endif// BOOST_VISITOR_VISITOR_PTR_HPP
118