/usr/include/boost/accumulators/framework/accumulators
Edit: /usr/include/boost/accumulators/framework/accumulators/droppable_accumulator.hpp (10136B)
///////////////////////////////////////////////////////////////////////////////
// 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
#include
#include
#include
#include // for feature_of
#include // for accumulator
namespace boost { namespace accumulators
{
template
struct droppable_accumulator;
namespace detail
{
///////////////////////////////////////////////////////////////////////////////
// add_ref_visitor
// a fusion function object for add_ref'ing accumulators
template
struct add_ref_visitor
{
explicit add_ref_visitor(Args const &args)
: args_(args)
{
}
template
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 >(
*this
);
}
private:
add_ref_visitor &operator =(add_ref_visitor const &);
Args const &args_;
};
template
add_ref_visitor make_add_ref_visitor(Args const &args)
{
return add_ref_visitor(args);
}
///////////////////////////////////////////////////////////////////////////////
// drop_visitor
// a fusion function object for dropping accumulators
template
struct drop_visitor
{
explicit drop_visitor(Args const &args)
: args_(args)
{
}
template
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 >(
*this
);
}
}
private:
drop_visitor &operator =(drop_visitor const &);
Args const &args_;
};
template
drop_visitor make_drop_visitor(Args const &args)
{
return drop_visitor(args);
}
}
//////////////////////////////////////////////////////////////////////////
// droppable_accumulator_base
template
struct droppable_accumulator_base
: Accumulator
{
typedef droppable_accumulator_base base;
typedef mpl::true_ is_droppable;
typedef typename Accumulator::result_type result_type;
template
droppable_accumulator_base(Args const &args)
: Accumulator(args)
, ref_count_(0)
{
}
droppable_accumulator_base(droppable_accumulator_base const &that)
: Accumulator(*static_cast(&that))
, ref_count_(that.ref_count_)
{
}
template
void operator ()(Args const &args)
{
if(!this->is_dropped())
{
this->Accumulator::operator ()(args);
}
}
template
void add_ref(Args const &)
{
++this->ref_count_;
}
template
void drop(Args const &args)
{
BOOST_ASSERT(0 < this->ref_count_);
if(1 == this->ref_count_)
{
static_cast *>(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
struct droppable_accumulator
: droppable_accumulator_base
{
template
droppable_accumulator(Args const &args)
: droppable_accumulator::base(args)
{
}
droppable_accumulator(droppable_accumulator const &that)
: droppable_accumulator::base(*static_cast(&that))
{
}
};
//////////////////////////////////////////////////////////////////////////
// with_cached_result
template
struct with_cached_result
: Accumulator
{
typedef typename Accumulator::result_type result_type;
template
with_cached_result(Args const &args)
: Accumulator(args)
, cache()
{
}
with_cached_result(with_cached_result const &that)
: Accumulator(*static_cast(&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
void on_drop(Args const &args)
{
// cache the result at the point this calculation was dropped
BOOST_ASSERT(!this->has_result());
this->set(this->Accumulator::result(args));
}
template
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 &r)
{
::new(this->cache.address()) result_type(r);
}
result_type const &get() const
{
return *static_cast(this->cache.address());
}
bool has_result() const
{
typedef with_cached_result this_type;
typedef droppable_accumulator_base derived_type;
return static_cast(this)->is_dropped();
}
aligned_storage cache;
};
namespace tag
{
template
struct as_droppable
{
typedef droppable type;
};
template
struct as_droppable >
{
typedef droppable type;
};
//////////////////////////////////////////////////////////////////////////
// droppable
template
struct droppable
: as_feature::type
{
typedef typename as_feature::type feature_type;
typedef typename feature_type::dependencies tmp_dependencies_;
typedef
typename mpl::transform<
typename feature_type::dependencies
, as_droppable
>::type
dependencies;
struct impl
{
template
struct apply
{
typedef
droppable_accumulator<
typename mpl::apply2::type
>
type;
};
};
};
}
// make droppable work
template
struct as_feature >
{
typedef tag::droppable::type> type;
};
// make droppable work with non-void weights (should become
// droppable
template
struct as_weighted_feature >
{
typedef tag::droppable::type> type;
};
// for the purposes of feature-based dependency resolution,
// droppable provides the same feature as Foo
template
struct feature_of >
: feature_of
{
};
// 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