1 //  Copyright (c) 2001-2011 Joel de Guzman
2 //  Copyright (c) 2001-2011 Hartmut Kaiser
3 //
4 //  Distributed under the Boost Software License, Version 1.0. (See accompanying
5 //  file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6 
7 #if !defined(BOOST_SPIRIT_KARMA_REFERENCE_APR_17_2009_1057PM)
8 #define BOOST_SPIRIT_KARMA_REFERENCE_APR_17_2009_1057PM
9 
10 #if defined(_MSC_VER)
11 #pragma once
12 #endif
13 
14 #include <boost/spirit/home/karma/meta_compiler.hpp>
15 #include <boost/spirit/home/karma/generator.hpp>
16 #include <boost/spirit/home/support/info.hpp>
17 #include <boost/spirit/home/support/handles_container.hpp>
18 #include <boost/type_traits/remove_const.hpp>
19 #include <boost/ref.hpp>
20 
21 namespace boost { namespace spirit { namespace karma
22 {
23     ///////////////////////////////////////////////////////////////////////////
24     // reference is a generator that references another generator (its Subject)
25     ///////////////////////////////////////////////////////////////////////////
26     template <typename Subject>
27     struct reference : generator<reference<Subject> >
28     {
29         typedef mpl::int_<generator_properties::all_properties> properties;
30 
31         typedef Subject subject_type;
32 
referenceboost::spirit::karma::reference33         reference(Subject& subject)
34           : ref(subject) {}
35 
36         template <typename Context, typename Unused>
37         struct attribute : Subject::template attribute<Context, Unused> {};
38 
39         // Default overload, used whenever the attribute is not unused and not
40         // used from an aliased rule.
41         template <typename OutputIterator, typename Context
42           , typename Delimiter, typename Attribute>
generateboost::spirit::karma::reference43         bool generate(OutputIterator& sink, Context& context
44           , Delimiter const& delim, Attribute const& attr) const
45         {
46             return ref.get().generate(sink, context, delim, attr);
47         }
48 
49         // This overload gets called from an aliased rule only, we take the
50         // attribute from the context provided from the wrapper rule.
51         template <typename OutputIterator, typename Context
52           , typename Delimiter>
generateboost::spirit::karma::reference53         bool generate(OutputIterator& sink, Context& context
54           , Delimiter const& delim, unused_type) const
55         {
56             return ref.get().generate(sink, context, delim, context.attributes);
57         }
58 
59         // This overload is used whenever no attribute is given and it is used
60         // not from an aliased rule.
61         template <typename OutputIterator, typename Delimiter>
generateboost::spirit::karma::reference62         bool generate(OutputIterator& sink, unused_type
63           , Delimiter const& delim, unused_type) const
64         {
65             return ref.get().generate(sink, unused, delim, unused);
66         }
67 
68         template <typename Context>
whatboost::spirit::karma::reference69         info what(Context& context) const
70         {
71             // the reference is transparent (does not add any info)
72             return ref.get().what(context);
73         }
74 
75         boost::reference_wrapper<Subject> ref;
76     };
77 }}}
78 
79 namespace boost { namespace spirit { namespace traits
80 {
81     ///////////////////////////////////////////////////////////////////////////
82     template <typename Subject, typename Attribute, typename Context
83       , typename Iterator>
84     struct handles_container<karma::reference<Subject>, Attribute
85       , Context, Iterator>
86       : handles_container<typename remove_const<Subject>::type, Attribute
87         , Context, Iterator>
88     {};
89 }}}
90 
91 #endif
92