⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 extension.qbk

📁 Boost provides free peer-reviewed portable C++ source libraries. We emphasize libraries that work
💻 QBK
📖 第 1 页 / 共 2 页
字号:
[/==============================================================================    Copyright (C) 2001-2007 Joel de Guzman, Dan Marsden, Tobias Schwinger    Use, modification and distribution is subject to the Boost Software    License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at    http://www.boost.org/LICENSE_1_0.txt)===============================================================================/][section Extension][section:ext_full The Full Extension Mechanism]The Fusion library is designed to be extensible, new sequences types can easilybe added. In fact, the library support for `std::pair`, `boost::array` and __mpl__sequences is entirely provided using the extension mechanism.The process for adding a new sequence type to Fusion is:# Enable the __tag_dispatching__ mechanism used by Fusion for your sequence type# Design an iterator type for the sequence# Provide specialized behaviour for the intrinsic operations of the new Fusion sequence[heading Our example]In order to illustrate enabling a new sequence type for use with Fusion, weare going to use the type:    namespace example    {        struct example_struct        {            std::string name;            int age;            example_struct(                const std::string& n,                int a)                : name(n), age(a)            {}        };    }We are going to pretend that this type has been provided by a 3rd partylibrary, and therefore cannot be modified. We shall work through all thenecessary steps to enable `example_struct` to serve as an __associative_sequence__as described in the __quick_start__ guide.[heading Enabling Tag Dispatching]The Fusion extensibility mechanism uses __tag_dispatching__ to call thecorrect code for a given sequence type. In order to exploit the tagdispatching mechanism we must first declare a new tag type for themechanism to use. For example:    namespace example {        struct example_sequence_tag; // Only definition needed    }Next we need to enable the `traits::tag_of` metafunction to return our newly chosentag type for operations involving our sequence. This is done by specializing`traits::tag_of` for our sequence type.    #include <boost/fusion/support/tag_of_fwd.hpp>    #include <boost/fusion/include/tag_of_fwd.hpp>    namespace boost { namespace fusion { namespace traits {        template<>        struct tag_of<example_struct>        {            typedef example::example_sequence_tag type;        };    }}}`traits::tag_of` also has a second template argument,that can be used in conjuction with `boost::enable_if` to provide tagsupport for groups of related types. This feature is not necessaryfor our sequence, but for an example see the code in:    #include <boost/fusion/adapted/array/tag_of.hpp>    #include <boost/fusion/include/tag_of.hpp>[heading Designing a suitable iterator]We need an iterator to describe positions, and provide access tothe data within our sequence. As it is straightforward to do,we are going to provide a random access iterator in our example.We will use a simple design, in which the 2 members of`example_struct` are given numbered indices, 0 for `name` and1 for `age` respectively.    template<typename Struct, int Pos>    struct example_struct_iterator        : boost::fusion::iterator_base<example_struct_iterator<Struct, Pos> >    {        BOOST_STATIC_ASSERT(Pos >=0 && Pos < 3);        typedef Struct struct_type;        typedef boost::mpl::int_<Pos> index;        typedef boost::fusion::random_access_traversal_tag category;        example_struct_iterator(Struct& str)            : struct_(str) {}        Struct& struct_;    };A quick summary of the details of our iterator:# The iterator is parameterized by the type it is iterating over, and the index of the current element.# The typedefs `struct_type` and `index` provide convenient access to information we will need later in  the implementation.# The typedef `category` allows the `traits::__category_of__` metafunction to establish  the traversal category of the iterator.# 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`traits::tag_of`.In isolation, the iterator implementation is pretty dry. Things should become clearer as weadd features to our implementation.[heading A first couple of instructive features]To start with, we will get the __result_of_value_of__ metafunction working. Todo this, we provide a specialization of the `boost::fusion::extension::value_of_impl` template forour iterator's tag type.    template<>    struct value_of_impl<example::example_struct_iterator_tag>    {        template<typename Iterator>        struct apply;        template<typename Struct>        struct apply<example::example_struct_iterator<Struct, 0> >        {            typedef std::string type;        };        template<typename Struct>        struct apply<example::example_struct_iterator<Struct, 1> >        {            typedef int type;        };    };The implementation itself is pretty simple, it just uses 2 partial specializations toprovide the type of the 2 different members of `example_struct`, based on the index of the iterator.To understand how `value_of_impl` is used by the library we will look at the implementation of __value_of__:    template <typename Iterator>    struct __value_of__        : extension::value_of_impl<typename detail::tag_of<Iterator>::type>::            template apply<Iterator>    {};So __value_of__ uses __tag_dispatching__ to select an __mpl_metafunction_class__to provide its functionality. You will notice this pattern throughout theimplementation of Fusion.Ok, lets enable dereferencing of our iterator. In this case we must provide a suitablespecialization of `deref_impl`.    template<>    struct deref_impl<example::example_struct_iterator_tag>    {        template<typename Iterator>        struct apply;        template<typename Struct>        struct apply<example::example_struct_iterator<Struct, 0> >        {            typedef typename mpl::if_<                is_const<Struct>, std::string const&, std::string&>::type type;            static type            call(example::example_struct_iterator<Struct, 0> const& it)            {                return it.struct_.name;            }        };        template<typename Struct>        struct apply<example::example_struct_iterator<Struct, 1> >        {            typedef typename mpl::if_<                is_const<Struct>, int const&, int&>::type type;            static type            call(example::example_struct_iterator<Struct, 1> const& it)            {                    return it.struct_.age;                }            };        };    }The use of `deref_impl` is very similar to that of `value_of_impl`, but it alsoprovides some runtime functionality this time via the `call` static member function.To see how `deref_impl` is used, lets have a look at the implementation of __deref__:    namespace result_of    {        template <typename Iterator>        struct __deref__            : extension::deref_impl<typename detail::tag_of<Iterator>::type>::                template apply<Iterator>        {};    }    template <typename Iterator>    typename result_of::deref<Iterator>::type    __deref__(Iterator const& i)    {        typedef result_of::deref<Iterator> deref_meta;        return deref_meta::call(i);    }So again __result_of_deref__ uses __tag_dispatching__ in exactly thesame way as the __value_of__ implementation. The runtime functionality usedby __deref__ is provided by the `call` static function of the selected__mpl_metafunction_class__.The actual implementation of `deref_impl` is slightly more complex than that of  `value_of_impl`.We also need to implement the `call` function, which returns a referenceto the appropriate member of the underlying sequence. We also require a littlebit of metaprogramming to return `const` references if the underlying sequenceis const.[note Although there is a fair amount of left to do to produce a fully fledgedFusion sequence, __value_of__ and __deref__ illustrate all the signficant conceptsrequired. The remainder of the process is very repetitive, simply requiringimplementation of a suitable `xxxx_impl` for each feature `xxxx`.][heading Implementing the remaining iterator functionality]Ok, now we have seen the way __value_of__ and __deref__ work, everything else will work in pretty much the same way. Lets start with forward iteration,by providing a `next_impl`:    template<>    struct next_impl<example::example_struct_iterator_tag>

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -