fixing exposing ftag, and namespace discipline issues

[SVN r35446]
This commit is contained in:
Dan Marsden
2006-10-02 21:18:39 +00:00
parent dbb2975df8
commit 9591dc6dd1

View File

@ -41,9 +41,9 @@ correct code for a given sequence type. In order to exploit the tag
dispatching mechanism we must first declare a new tag type for the dispatching mechanism we must first declare a new tag type for the
mechanism to use. For example: mechanism to use. For example:
namespace boost { namespace fusion { namespace example {
struct example_sequence_tag; // Only definition needed struct example_sequence_tag; // Only definition needed
}} }
Next we need to enable the `traits::tag_of` metafunction to return our newly chosen Next we need to enable the `traits::tag_of` metafunction to return our newly chosen
tag type for operations involving our sequence. This is done by specializing tag type for operations involving our sequence. This is done by specializing
@ -52,17 +52,16 @@ tag type for operations involving our sequence. This is done by specializing
#include <boost/fusion/support/tag_of_fwd.hpp> #include <boost/fusion/support/tag_of_fwd.hpp>
namespace boost { namespace fusion { namespace traits { namespace boost { namespace fusion { namespace traits {
template<> template<>
struct tag_of<example_struct> struct tag_of<example_struct>
{ {
typedef example_sequence_tag type; typedef example::example_sequence_tag type;
}; };
}}} }}}
`traits::tag_of` also has a second template argument, `traits::tag_of` also has a second template argument,
that can be used in conjuction with `boost::enable_if` to provide tag that can be used in conjuction with `boost::enable_if` to provide tag
support for whole clases of types. This feature is not necessary support for groups of related types. This feature is not necessary
for our sequence, but for an example see the code in: for our sequence, but for an example see the code in:
#include <boost/fusion/sequence/adapted/mpl/tag_of.hpp> #include <boost/fusion/sequence/adapted/mpl/tag_of.hpp>
@ -79,12 +78,12 @@ We will use a simple design, in which the 2 members of
template<typename Struct, int Pos> template<typename Struct, int Pos>
struct example_struct_iterator struct example_struct_iterator
: iterator_base<example_struct_iterator<Struct, Pos> > : boost::fusion::iterator_base<example_struct_iterator<Struct, Pos> >
{ {
BOOST_STATIC_ASSERT(Pos >=0 && Pos < 3); BOOST_STATIC_ASSERT(Pos >=0 && Pos < 3);
typedef Struct struct_type; typedef Struct struct_type;
typedef mpl::int_<Pos> index; typedef boost::mpl::int_<Pos> index;
typedef random_access_traversal_tag category; typedef boost::fusion::random_access_traversal_tag category;
example_struct_iterator(Struct& str) example_struct_iterator(Struct& str)
: struct_(str) {} : struct_(str) {}
@ -102,20 +101,7 @@ A quick summary of the details of our iterator:
# The constructor stores a reference to the `example_struct` being iterated over. # The constructor stores a reference to the `example_struct` being iterated over.
We also need to enable __tag_dispatching__ for our iterator type, with another specialization of We also need to enable __tag_dispatching__ for our iterator type, with another specialization of
`traits::tag_of`: `traits::tag_of`.
namespace boost { namespace fusion {
struct example_struct_iterator_tag;
namespace traits
{
template<typename Struct, int Pos>
struct tag_of<boost::fusion::example_struct_iterator<Struct, Pos> >
{
typedef example_struct_iterator_tag type;
};
}
}}
In isolation, the iterator implementation is pretty dry. Things should become clearer as we In isolation, the iterator implementation is pretty dry. Things should become clearer as we
add features to our implementation. add features to our implementation.
@ -127,19 +113,19 @@ do this, we provide a specialization of the `boost::fusion::extension::value_of_
our iterator's tag type. our iterator's tag type.
template<> template<>
struct value_of_impl<example_struct_iterator_tag> struct value_of_impl<example::example_struct_iterator_tag>
{ {
template<typename Iterator> template<typename Iterator>
struct apply; struct apply;
template<typename Struct> template<typename Struct>
struct apply<example_struct_iterator<Struct, 0> > struct apply<example::example_struct_iterator<Struct, 0> >
{ {
typedef std::string type; typedef std::string type;
}; };
template<typename Struct> template<typename Struct>
struct apply<example_struct_iterator<Struct, 1> > struct apply<example::example_struct_iterator<Struct, 1> >
{ {
typedef int type; typedef int type;
}; };
@ -152,12 +138,9 @@ To understand how `value_of_impl` is used by the library we will look at the imp
template <typename Iterator> template <typename Iterator>
struct __value_of__ struct __value_of__
{ : extension::value_of_impl<typename detail::tag_of<Iterator>::type>::
typedef typename template apply<Iterator>
extension::value_of_impl<typename Iterator::fusion_tag>:: {};
template apply<Iterator>::type
type;
};
So __value_of__ uses __tag_dispatching__ to select an __mpl_metafunction_class__ So __value_of__ uses __tag_dispatching__ to select an __mpl_metafunction_class__
to provide its functionality. You will notice this pattern throughout the to provide its functionality. You will notice this pattern throughout the
@ -167,37 +150,38 @@ Ok, lets enable dereferencing of our iterator. In this case we must provide a su
specialization of `deref_impl`. specialization of `deref_impl`.
template<> template<>
struct deref_impl<example_struct_iterator_tag> struct deref_impl<example::example_struct_iterator_tag>
{ {
template<typename Iterator> template<typename Iterator>
struct apply; struct apply;
template<typename Struct> template<typename Struct>
struct apply<example_struct_iterator<Struct, 0> > struct apply<example::example_struct_iterator<Struct, 0> >
{ {
typedef typename mpl::if_< typedef typename mpl::if_<
is_const<Struct>, std::string const&, std::string&>::type type; is_const<Struct>, std::string const&, std::string&>::type type;
static type static type
call(example_struct_iterator<Struct, 0> const& it) call(example::example_struct_iterator<Struct, 0> const& it)
{ {
return it.struct_.name; return it.struct_.name;
} }
}; };
template<typename Struct> template<typename Struct>
struct apply<example_struct_iterator<Struct, 1> > struct apply<example::example_struct_iterator<Struct, 1> >
{ {
typedef typename mpl::if_< typedef typename mpl::if_<
is_const<Struct>, int const&, int&>::type type; is_const<Struct>, int const&, int&>::type type;
static type static type
call(example_struct_iterator<Struct, 1> const& it) call(example::example_struct_iterator<Struct, 1> const& it)
{ {
return it.struct_.age; return it.struct_.age;
} }
};
}; };
}; }
The use of `deref_impl` is very similar to that of `value_of_impl`, but it also The use of `deref_impl` is very similar to that of `value_of_impl`, but it also
provides some runtime functionality this time via the `call` static member function. provides some runtime functionality this time via the `call` static member function.
@ -207,20 +191,17 @@ To see how `deref_impl` is used, lets have a look at the implementation of __der
{ {
template <typename Iterator> template <typename Iterator>
struct __deref__ struct __deref__
{ : extension::deref_impl<typename detail::tag_of<Iterator>::type>::
typedef typename template apply<Iterator>
deref_impl<typename Iterator::fusion_tag>:: {};
template apply<Iterator>::type
type;
};
} }
template <typename Iterator> template <typename Iterator>
typename __result_of_deref__<Iterator>::type typename result_of::deref<Iterator>::type
__deref__(Iterator const& i) __deref__(Iterator const& i)
{ {
return extension::deref_impl<typename Iterator::fusion_tag>:: typedef result_of::deref<Iterator> deref_meta;
template apply<Iterator>::call(i); return deref_meta::call(i);
} }
So again __result_of_deref__ uses __tag_dispatching__ in exactly the So again __result_of_deref__ uses __tag_dispatching__ in exactly the
@ -247,19 +228,19 @@ Ok, now we have seen the way __value_of__ and __deref__ work, everything else wi
by providing a `next_impl`: by providing a `next_impl`:
template<> template<>
struct next_impl<example_struct_iterator_tag> struct next_impl<example::example_struct_iterator_tag>
{ {
template<typename Iterator> template<typename Iterator>
struct apply struct apply
{ {
typedef typename Iterator::struct_type struct_type; typedef typename Iterator::struct_type struct_type;
typedef typename Iterator::index index; typedef typename Iterator::index index;
typedef example_struct_iterator<struct_type, index::value + 1> type; typedef example::example_struct_iterator<struct_type, index::value + 1> type;
static type static type
call(Iterator const& i) call(Iterator const& i)
{ {
return type(i.struct_); return type(i.struct_);
} }
}; };
}; };
@ -285,12 +266,12 @@ In order that Fusion can correctly identify our sequence as a Fusion sequence, w
need to enable `is_sequence` for our sequence type. As usual we just create need to enable `is_sequence` for our sequence type. As usual we just create
an `impl` type specialized for our sequence tag: an `impl` type specialized for our sequence tag:
template<> template<>
struct is_sequence_impl<example_sequence_tag> struct is_sequence_impl<example::example_sequence_tag>
{ {
template<typename T> template<typename T>
struct apply : mpl::true_ {}; struct apply : mpl::true_ {};
}; };
We've some similar formalities to complete, providing `category_of_impl` so Fusion We've some similar formalities to complete, providing `category_of_impl` so Fusion
can correctly identify our sequence type, and `is_view_impl` so Fusion can correctly can correctly identify our sequence type, and `is_view_impl` so Fusion can correctly
@ -302,12 +283,12 @@ __begin__ working so that we can get an iterator to start accessing the data in
our sequence. our sequence.
template<> template<>
struct begin_impl<example_sequence_tag> struct begin_impl<example::example_sequence_tag>
{ {
template<typename Sequence> template<typename Sequence>
struct apply struct apply
{ {
typedef example_struct_iterator<Sequence, 0> type; typedef example::example_struct_iterator<Sequence, 0> type;
static type static type
call(Sequence& seq) call(Sequence& seq)
@ -337,7 +318,7 @@ types described in the __quick_start__ guide with the appropriate members of `ex
Our implementation is as follows: Our implementation is as follows:
template<> template<>
struct at_key_impl<example_sequence_tag> struct at_key_impl<example::example_sequence_tag>
{ {
template<typename Sequence, typename Key> template<typename Sequence, typename Key>
struct apply; struct apply;