source: NonGTP/Boost/boost/variant/get.hpp @ 857

Revision 857, 5.2 KB checked in by igarcia, 18 years ago (diff)
Line 
1//-----------------------------------------------------------------------------
2// boost variant/get.hpp header file
3// See http://www.boost.org for updates, documentation, and revision history.
4//-----------------------------------------------------------------------------
5//
6// Copyright (c) 2003
7// Eric Friedman, Itay Maman
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_GET_HPP
14#define BOOST_VARIANT_GET_HPP
15
16#include <exception>
17
18#include "boost/config.hpp"
19#include "boost/detail/workaround.hpp"
20#include "boost/utility/addressof.hpp"
21#include "boost/variant/variant_fwd.hpp"
22
23#include "boost/type_traits/add_reference.hpp"
24#include "boost/type_traits/add_pointer.hpp"
25
26#if BOOST_WORKAROUND(BOOST_MSVC, <= 1200)
27#   include "boost/mpl/bool.hpp"
28#   include "boost/mpl/or.hpp"
29#   include "boost/type_traits/is_same.hpp"
30#endif
31
32namespace boost {
33
34//////////////////////////////////////////////////////////////////////////
35// class bad_get
36//
37// The exception thrown in the event of a failed get of a value.
38//
39class bad_get
40    : public std::exception
41{
42public: // std::exception implementation
43
44    virtual const char * what() const throw()
45    {
46        return "boost::bad_get: "
47               "failed value get using boost::get";
48    }
49
50};
51
52//////////////////////////////////////////////////////////////////////////
53// function template get<T>
54//
55// Retrieves content of given variant object if content is of type T.
56// Otherwise: pointer ver. returns 0; reference ver. throws bad_get.
57//
58
59namespace detail { namespace variant {
60
61// (detail) class template get_visitor
62//
63// Generic static visitor that: if the value is of the specified type,
64// returns a pointer to the value it visits; else a null pointer.
65//
66template <typename T>
67struct get_visitor
68{
69private: // private typedefs
70
71    typedef typename add_pointer<T>::type pointer;
72    typedef typename add_reference<T>::type reference;
73
74public: // visitor typedefs
75
76    typedef pointer result_type;
77
78public: // visitor interfaces
79
80#if !BOOST_WORKAROUND(BOOST_MSVC, <= 1200)
81
82    pointer operator()(reference operand) const
83    {
84        return boost::addressof(operand);
85    }
86
87    template <typename U>
88    pointer operator()(const U&) const
89    {
90        return static_cast<pointer>(0);
91    }
92
93#else // MSVC6
94
95private: // helpers, for visitor interfaces (below)
96
97    pointer execute_impl(reference operand, mpl::true_) const
98    {
99        return boost::addressof(operand);
100    }
101
102    template <typename U>
103    pointer execute_impl(const U& operand, mpl::false_) const
104    {
105        return static_cast<pointer>(0);
106    }
107
108public: // visitor interfaces
109
110    template <typename U>
111    pointer operator()(U& operand) const
112    {
113        // MSVC6 finds normal implementation (above) ambiguous,
114        // so we must explicitly disambiguate
115
116        typedef typename mpl::or_<
117              is_same<U, T>
118            , is_same<const U, T>
119            >::type U_is_T;
120
121        return execute_impl(operand, U_is_T());
122    }
123
124#endif // MSVC6 workaround
125
126};
127
128}} // namespace detail::variant
129
130#if !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x0551))
131#   define BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(t)  \
132    BOOST_APPEND_EXPLICIT_TEMPLATE_TYPE(t)
133#else
134#   define BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(t)  \
135    , t* = 0
136#endif
137
138template <typename U, BOOST_VARIANT_ENUM_PARAMS(typename T) >
139inline
140    typename add_pointer<U>::type
141get(
142      boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >* operand
143      BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(U)
144    )
145{
146    typedef typename add_pointer<U>::type U_ptr;
147    if (!operand) return static_cast<U_ptr>(0);
148
149    detail::variant::get_visitor<U> v;
150    return operand->apply_visitor(v);
151}
152
153template <typename U, BOOST_VARIANT_ENUM_PARAMS(typename T) >
154inline
155    typename add_pointer<const U>::type
156get(
157      const boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >* operand
158      BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(U)
159    )
160{
161    typedef typename add_pointer<const U>::type U_ptr;
162    if (!operand) return static_cast<U_ptr>(0);
163
164    detail::variant::get_visitor<const U> v;
165    return operand->apply_visitor(v);
166}
167
168template <typename U, BOOST_VARIANT_ENUM_PARAMS(typename T) >
169inline
170    typename add_reference<U>::type
171get(
172      boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >& operand
173      BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(U)
174    )
175{
176    typedef typename add_pointer<U>::type U_ptr;
177    U_ptr result = get<U>(&operand);
178
179    if (!result)
180        throw bad_get();
181    return *result;
182}
183
184template <typename U, BOOST_VARIANT_ENUM_PARAMS(typename T) >
185inline
186    typename add_reference<const U>::type
187get(
188      const boost::variant< BOOST_VARIANT_ENUM_PARAMS(T) >& operand
189      BOOST_VARIANT_AUX_GET_EXPLICIT_TEMPLATE_TYPE(U)
190    )
191{
192    typedef typename add_pointer<const U>::type U_ptr;
193    U_ptr result = get<const U>(&operand);
194
195    if (!result)
196        throw bad_get();
197    return *result;
198}
199
200} // namespace boost
201
202#endif // BOOST_VARIANT_GET_HPP
Note: See TracBrowser for help on using the repository browser.