Commit d75e6fa4 authored by Edwin Carlinet's avatar Edwin Carlinet
Browse files

Fix accumulator issue with dynamic parameter in meta accumulators.

Fix affects also the Kernel Library that uses aggregators.
parent b35b7008
......@@ -5,26 +5,71 @@
# include <mln/accu/feature.hpp>
# include <mln/accu/composite_accumulator.hpp>
/// \defgroup accu Accumulator framework
/// \{
/// \file
/// \brief Header file for the accumulator framework
namespace mln
{
namespace accu
{
/// \brief The namespace for accumulator features.
namespace features
{
}
/// \brief The namespace for accumulator object themselves.
namespace accumulators
{
}
/// \brief The namespace for feature extractor.
namespace extractor
{
}
/// \defgroup freefun Free functions
/// \{
# ifdef MLN_DOXYGEN
/// \brief Make a concrete accumulator from an accumulator-like object \p accu.
/// If \p accu is a feature-set, it is bound to the argument type of \p arg, otherwise
/// \tparam A the accumulator-like type.
/// \tparam T the value type to accumulate
/// \param accu the accumulator-like object
/// \param arg a value prototype to accumulate
///
/// \code
/// accu::features::max<> myfeat;
/// auto myaccu = accu::make_accumulator(myfeat, int());
/// myaccu.init();
/// myaccu.take(15); myaccu.take(5);
/// int m = myaccu.to_result() // 15
/// \endcode
///
template <typename A, typename T>
unspecified make_accumulator(const AccumulatorLike<A>& accu, T arg);
/// \brief Helper structure to get the return type of an accumulator-like object.
/// It defines an internal member type named \p type which is the result type
/// of the accumulator
/// \tparam AccuLike The type of the accumulator-like object.
/// \tparam T The argument type (the type of values to accumulate)
/// \tparam Extractor The function used to extract the result from the accumulator
template <typename AccuLike, typename T, typename Extractor = default_extractor>
struct result_of
{
typedef unspecified type;
};
/// \brief The defaut extractor
/// It calls the `to_result` method of the accumulator.
struct default_extractor;
# endif
# ifndef MLN_DOXYGEN
template <typename A, typename ...>
A& make_accumulator(Accumulator<A>& accu);
......@@ -34,46 +79,46 @@ namespace mln
template <typename F, typename T>
typename F::template apply<T>::type
make_accumulator(const FeatureSet<F>& feat, T = T());
/// \}
struct default_extractor
{
template <typename A>
typename A::result_type
operator() (const Accumulator<A>& accu) const
{
template <typename A>
typename A::result_type
operator() (const Accumulator<A>& accu) const
{
return exact(accu).to_result();
}
};
}
};
# endif
template <typename AccuLike, typename T, typename Extractor = default_extractor,
typename Enabler = void>
typename Enabler = void>
struct result_of
{
static_assert( std::is_convertible<AccuLike, FeatureSet<AccuLike> >::value,
"sdfsd");
};
static_assert( std::is_convertible<AccuLike, FeatureSet<AccuLike> >::value,
"sdfsd");
};
template <typename AccuLike, typename T, typename Extractor>
struct result_of<AccuLike, T, Extractor,
typename std::enable_if< is_a<AccuLike, FeatureSet>::value >::type>
typename std::enable_if< is_a<AccuLike, FeatureSet>::value >::type>
{
private:
typedef typename AccuLike::template apply<T>::type Accu;
private:
typedef typename AccuLike::template apply<T>::type Accu;
public:
typedef typename std::result_of<Extractor(Accu)>::type type;
};
public:
typedef typename std::result_of<Extractor(Accu)>::type type;
};
template <typename AccuLike, typename T, typename Extractor>
struct result_of<AccuLike, T, Extractor,
typename std::enable_if< is_a<AccuLike, Accumulator>::value >::type>
typename std::enable_if< is_a<AccuLike, Accumulator>::value >::type>
{
typedef typename std::result_of<Extractor(AccuLike)>::type type;
};
typedef typename std::result_of<Extractor(AccuLike)>::type type;
};
......@@ -88,8 +133,8 @@ namespace mln
template <typename A, typename ...>
A& make_accumulator(Accumulator<A>& accu)
{
return exact(accu);
}
return exact(accu);
}
template <typename A, typename ...>
const A& make_accumulator(const Accumulator<A>& accu, ...)
......@@ -99,13 +144,15 @@ namespace mln
template <typename F, typename T>
typename F::template apply<T>::type
make_accumulator(const FeatureSet<F>&, T)
make_accumulator(const FeatureSet<F>& fs, T)
{
return typename F::template apply<T>::type ();
}
return exact(fs).template make<T>();
}
}
}
}
/// \}
#endif // ! ACCUMULATOR_HPP
#ifndef MLN_ACCU_ACCUMULATOTS_COUNT_HPP
# define MLN_ACCU_ACCUMULATOTS_COUNT_HPP
/// \file
/// \brief Header file for counting accumulator.
# include <mln/accu/accumulator_base.hpp>
# include <mln/accu/dontcare.hpp>
# include <utility>
......@@ -12,6 +15,9 @@ namespace mln
{
namespace accumulators
{
/// \brief The counting accumulator.
/// \tparam CountType is underlying the counter type (it must be incrementable,
/// and decrementable.
template <typename CountType = std::size_t>
struct count;
}
......@@ -29,9 +35,9 @@ namespace mln
inline
auto
count(const Accumulator<A>& acc)
-> decltype(extract(exact(acc), features::count<> ()))
-> decltype(extract(exact(acc), features::count<> ()))
{
return extract(exact(acc), features::count<> ());
return extract(exact(acc), features::count<> ());
}
}
......@@ -39,17 +45,22 @@ namespace mln
namespace features
{
template <typename CountType>
struct count : simple_feature< count<CountType> >
{
template <typename T>
struct apply
{
typedef accumulators::count<CountType> type;
};
template <typename T>
struct apply
{
typedef accumulators::count<CountType> type;
};
template <typename T>
accumulators::count<CountType>
make()
{
return accumulators::count<CountType> ();
}
};
}
namespace accumulators
......@@ -58,44 +69,44 @@ namespace mln
template <typename CountType>
struct count : accumulator_base< count<CountType>, dontcare, CountType, features::count<> >
{
typedef dontcare argument_type;
typedef CountType return_type;
typedef boost::mpl::set< features::count<> > provides;
count()
: m_count (0)
{
}
void init()
{
m_count = 0;
}
void take(const dontcare&)
{
++m_count;
}
void untake(const dontcare&)
{
--m_count;
}
template <typename Other>
void take(const Accumulator<Other>& other)
{
m_count += extractor::count(other);
}
friend
return_type extract(const count& accu, features::count<> )
{
return accu.m_count;
}
typedef dontcare argument_type;
typedef CountType result_type;
typedef boost::mpl::set< features::count<> > provides;
count()
: m_count (0)
{
}
void init()
{
m_count = 0;
}
void take(const dontcare&)
{
++m_count;
}
void untake(const dontcare&)
{
--m_count;
}
template <typename Other>
void take(const Accumulator<Other>& other)
{
m_count += extractor::count(other);
}
friend
result_type extract(const count& accu, features::count<> )
{
return accu.m_count;
}
private:
CountType m_count;
CountType m_count;
};
}
......
......@@ -11,11 +11,18 @@ namespace mln
namespace accu
{
namespace accumulators
{
template <typename T, typename Compare = productorder_less<T> >
struct infsup;
template <typename T, typename Compare = std::less<T> >
struct sup;
template <typename T, typename Compare = std::less<T> >
struct inf;
}
namespace features
......@@ -33,17 +40,17 @@ namespace mln
template <typename A>
auto
inf(const Accumulator<A>& acc)
-> decltype( extract(exact(acc), features::inf<> ()) )
-> decltype( extract(exact(acc), features::inf<> ()) )
{
return extract(exact(acc), features::inf<> ());
return extract(exact(acc), features::inf<> ());
}
template <typename A>
auto
sup(const Accumulator<A>& acc)
-> decltype( extract(exact(acc), features::sup<> ()) )
-> decltype( extract(exact(acc), features::sup<> ()) )
{
return extract(exact(acc), features::sup<> ());
return extract(exact(acc), features::sup<> ());
}
}
......@@ -55,43 +62,93 @@ namespace mln
template <typename Compare>
struct inf : simple_feature< inf<Compare> >
{
template <typename T>
struct apply
{
typedef accumulators::infsup<T, Compare> type;
};
inf(const Compare& cmp)
: m_cmp(cmp)
{
}
template <typename T>
struct apply
{
typedef accumulators::sup<T, Compare> type;
};
template <typename T>
accumulators::sup<T, Compare>
make() const
{
return accumulators::sup<T, Compare>(m_cmp);
}
private:
Compare m_cmp;
};
template <>
struct inf<void> : simple_feature< inf<void> >
{
template <typename T>
struct apply
{
typedef accumulators::infsup<T, std::less<T> > type;
};
inf() = default;
template <typename T>
struct apply
{
typedef accumulators::sup<T> type;
};
template <typename T>
accumulators::sup<T>
make() const
{
return accumulators::sup<T>();
}
};
template <typename Compare>
struct sup : simple_feature< sup<Compare> >
{
template <typename T>
struct apply
{
typedef accumulators::infsup<T, Compare> type;
};
sup(const Compare& cmp)
: m_cmp(cmp)
{
}
template <typename T>
struct apply
{
typedef accumulators::sup<T, Compare> type;
};
template <typename T>
accumulators::sup<T, Compare>
make() const
{
return accumulators::sup<T, Compare>(m_cmp);
}
private:
Compare m_cmp;
};
template <>
struct sup<void> : simple_feature< sup<void> >
{
template <typename T>
struct apply
{
typedef accumulators::infsup<T, std::less<T> > type;
};
sup() = default;
template <typename T>
struct apply
{
typedef accumulators::sup<T> type;
};
template <typename T>
accumulators::sup<T>
make() const
{
return accumulators::sup<T>();
}
};
}
namespace accumulators
......@@ -100,62 +157,162 @@ namespace mln
template <typename T, typename Compare>
struct infsup : Accumulator< infsup<T, Compare> >
{
typedef T argument_type;
typedef std::pair<T,T> result_type;
typedef boost::mpl::set<
features::inf<>, features::sup<> > provides;
infsup(const Compare& cmp = Compare())
: m_inf( value_traits<T, Compare>::sup() ),
m_sup( value_traits<T, Compare>::inf() ),
m_cmp( cmp )
{
}
void init()
{
m_inf = value_traits<T, Compare>::sup();
m_sup = value_traits<T, Compare>::inf();
}
void take(const T& v)
{
m_inf = inf(m_inf, v, m_cmp);
m_sup = sup(m_sup, v, m_cmp);
}
template <typename Other>
void take(const Accumulator<Other>& other)
{
T vinf = extractor::inf(other);
T vsup = extractor::sup(other);
m_inf = inf(m_inf, vinf, m_cmp);
m_sup = sup(m_sup, vsup, m_cmp);
}
std::pair<T, T> to_result() const
{
return std::make_pair(m_inf, m_sup);
}
friend
T extract(const infsup& accu, features::inf<> )
{
return accu.m_inf;
}
friend
T extract(const infsup& accu, features::sup<> )
{
return accu.m_sup;
}
typedef T argument_type;
typedef std::pair<T,T> result_type;
typedef boost::mpl::set<
features::inf<>, features::sup<> > provides;
infsup(const Compare& cmp = Compare())
: m_inf( value_traits<T, Compare>::sup() ),
m_sup( value_traits<T, Compare>::inf() ),
m_cmp( cmp )
{
}
void init()
{
m_inf = value_traits<T, Compare>::sup();
m_sup = value_traits<T, Compare>::inf();
}
void take(const T& v)
{
using mln::inf;
using mln::sup;
m_inf = inf(m_inf, v, m_cmp);
m_sup = sup(m_sup, v, m_cmp);
}
template <typename Other>
void take(const Accumulator<Other>& other)
{
using mln::inf;
using mln::sup;
T vinf = extractor::inf(other);
T vsup = extractor::sup(other);
m_inf = inf(m_inf, vinf, m_cmp);
m_sup = sup(m_sup, vsup, m_cmp);
}
std::pair<T, T> to_result() const
{
return std::make_pair(m_inf, m_sup);
}
friend
T extract(const infsup& accu, features::inf<> )
{
return accu.m_inf;
}
friend
T extract(const infsup& accu, features::sup<> )
{
return accu.m_sup;
}
private:
T m_inf;
T m_sup;
Compare m_cmp;
};
template <typename T, typename Compare>
struct inf : Accumulator< inf<T, Compare> >
{
typedef T argument_type;
typedef T result_type;
inf(const Compare& cmp = Compare())
: m_cmp( cmp ),
m_inf( value_traits<T, Compare>::sup() )
{
}
void init()
{
m_inf = value_traits<T, Compare>::sup();
}
void take(const T& v)
{
using mln::inf;
m_inf = inf(m_inf, v, m_cmp);
}
template <typename Other>
void take(const Accumulator<Other>& other)
{
using mln::inf;
T vinf = extractor::inf(other);
m_inf = inf(m_inf, vinf, m_cmp);
}
T to_result() const
{
return m_inf;
}