droppable_accumulator.hpp

来自「Boost provides free peer-reviewed portab」· HPP 代码 · 共 318 行

HPP
318
字号
///////////////////////////////////////////////////////////////////////////////// droppable_accumulator.hpp////  Copyright 2005 Eric Niebler. Distributed under 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)#ifndef BOOST_ACCUMULATORS_FRAMEWORK_ACCUMULATORS_DROPPABLE_ACCUMULATOR_HPP_EAN_13_12_2005#define BOOST_ACCUMULATORS_FRAMEWORK_ACCUMULATORS_DROPPABLE_ACCUMULATOR_HPP_EAN_13_12_2005#include <new>#include <boost/assert.hpp>#include <boost/mpl/apply.hpp>#include <boost/aligned_storage.hpp>#include <boost/accumulators/framework/depends_on.hpp> // for feature_of#include <boost/accumulators/framework/parameters/accumulator.hpp> // for accumulatornamespace boost { namespace accumulators{    template<typename Accumulator>    struct droppable_accumulator;    namespace detail    {        ///////////////////////////////////////////////////////////////////////////////        // add_ref_visitor        //   a fusion function object for add_ref'ing accumulators        template<typename Args>        struct add_ref_visitor        {            explicit add_ref_visitor(Args const &args)              : args_(args)            {            }            template<typename Accumulator>            void operator ()(Accumulator &acc) const            {                typedef typename Accumulator::feature_tag::dependencies dependencies;                acc.add_ref(this->args_);                // Also add_ref accumulators that this feature depends on                this->args_[accumulator].template                    visit_if<detail::contains_feature_of_<dependencies> >(                        *this                );            }        private:            add_ref_visitor &operator =(add_ref_visitor const &);            Args const &args_;        };        template<typename Args>        add_ref_visitor<Args> make_add_ref_visitor(Args const &args)        {            return add_ref_visitor<Args>(args);        }        ///////////////////////////////////////////////////////////////////////////////        // drop_visitor        //   a fusion function object for dropping accumulators        template<typename Args>        struct drop_visitor        {            explicit drop_visitor(Args const &args)              : args_(args)            {            }            template<typename Accumulator>            void operator ()(Accumulator &acc) const            {                if(typename Accumulator::is_droppable())                {                    typedef typename Accumulator::feature_tag::dependencies dependencies;                    acc.drop(this->args_);                    // Also drop accumulators that this feature depends on                    this->args_[accumulator].template                        visit_if<detail::contains_feature_of_<dependencies> >(                            *this                    );                }            }        private:            drop_visitor &operator =(drop_visitor const &);            Args const &args_;        };        template<typename Args>        drop_visitor<Args> make_drop_visitor(Args const &args)        {            return drop_visitor<Args>(args);        }    }    //////////////////////////////////////////////////////////////////////////    // droppable_accumulator_base    template<typename Accumulator>    struct droppable_accumulator_base      : Accumulator    {        typedef droppable_accumulator_base base;        typedef mpl::true_ is_droppable;        typedef typename Accumulator::result_type result_type;        template<typename Args>        droppable_accumulator_base(Args const &args)          : Accumulator(args)          , ref_count_(0)        {        }        template<typename Args>        void operator ()(Args const &args)        {            if(!this->is_dropped())            {                this->Accumulator::operator ()(args);            }        }        template<typename Args>        void add_ref(Args const &)        {            ++this->ref_count_;        }        template<typename Args>        void drop(Args const &args)        {            BOOST_ASSERT(0 < this->ref_count_);            if(1 == this->ref_count_)            {                static_cast<droppable_accumulator<Accumulator> *>(this)->on_drop(args);            }            --this->ref_count_;        }        bool is_dropped() const        {            return 0 == this->ref_count_;        }    private:        int ref_count_;    };    //////////////////////////////////////////////////////////////////////////    // droppable_accumulator    //   this can be specialized for any type that needs special handling    template<typename Accumulator>    struct droppable_accumulator      : droppable_accumulator_base<Accumulator>    {        template<typename Args>        droppable_accumulator(Args const &args)          : droppable_accumulator::base(args)        {        }    };    //////////////////////////////////////////////////////////////////////////    // with_cached_result    template<typename Accumulator>    struct with_cached_result      : Accumulator    {        typedef typename Accumulator::result_type result_type;        template<typename Args>        with_cached_result(Args const &args)          : Accumulator(args)          , cache()        {        }        with_cached_result(with_cached_result const &that)          : Accumulator(*static_cast<Accumulator const *>(&that))          , cache()        {            if(that.has_result())            {                this->set(that.get());            }        }        ~with_cached_result()        {            // Since this is a base class of droppable_accumulator_base,            // this destructor is called before any of droppable_accumulator_base's            // members get cleaned up, including is_dropped, so the following            // call to has_result() is valid.            if(this->has_result())            {                this->get().~result_type();            }        }        template<typename Args>        void on_drop(Args const &args)        {            // cache the result at the point this calcuation was dropped            BOOST_ASSERT(!this->has_result());            this->set(this->Accumulator::result(args));        }        template<typename Args>        result_type result(Args const &args) const        {            return this->has_result() ? this->get() : this->Accumulator::result(args);        }    private:        with_cached_result &operator =(with_cached_result const &);        void set(result_type const &result)        {            ::new(this->cache.address()) result_type(result);        }        result_type const &get() const        {            return *static_cast<result_type const *>(this->cache.address());        }        bool has_result() const        {            typedef with_cached_result<Accumulator> this_type;            typedef droppable_accumulator_base<this_type> derived_type;            return static_cast<derived_type const *>(this)->is_dropped();        }        aligned_storage<sizeof(result_type)> cache;    };    namespace tag    {        template<typename Feature>        struct as_droppable        {            typedef droppable<Feature> type;        };        template<typename Feature>        struct as_droppable<droppable<Feature> >        {            typedef droppable<Feature> type;        };        //////////////////////////////////////////////////////////////////////////        // droppable        template<typename Feature>        struct droppable          : as_feature<Feature>::type        {            typedef typename as_feature<Feature>::type feature_type;            typedef typename feature_type::dependencies tmp_dependencies_;            typedef                typename mpl::transform<                    typename feature_type::dependencies                  , as_droppable<mpl::_1>                >::type            dependencies;            struct impl            {                template<typename Sample, typename Weight>                struct apply                {                    typedef                        droppable_accumulator<                            typename mpl::apply2<typename feature_type::impl, Sample, Weight>::type                        >                    type;                };            };        };    }    // make droppable<tag::feature(modifier)> work    template<typename Feature>    struct as_feature<tag::droppable<Feature> >    {        typedef tag::droppable<typename as_feature<Feature>::type> type;    };    // make droppable<tag::mean> work with non-void weights (should become    // droppable<tag::weighted_mean>    template<typename Feature>    struct as_weighted_feature<tag::droppable<Feature> >    {        typedef tag::droppable<typename as_weighted_feature<Feature>::type> type;    };    // for the purposes of feature-based dependency resolution,    // droppable<Foo> provides the same feature as Foo    template<typename Feature>    struct feature_of<tag::droppable<Feature> >      : feature_of<Feature>    {    };    // Note: Usually, the extractor is pulled into the accumulators namespace with    // a using directive, not the tag. But the droppable<> feature doesn't have an    // extractor, so we can put the droppable tag in the accumulators namespace    // without fear of a name conflict.    using tag::droppable;}} // namespace boost::accumulators#endif

⌨️ 快捷键说明

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