|
Boost : |
Subject: [boost] RFC: Sequence Properties and Boost Algorithm/Functional
From: Grant Erickson (gerickson_at_[hidden])
Date: 2010-01-22 17:02:32
For a recent project, I needed to inquire about a sequence of objects and
make a determination as to whether the sequences were:
* Increasing
* Strictly Increasing
* Decreasing
* Strictly Decreasing
Looking through STL, Boost documentation, Boost sources and headers and the
Boost mailing lists I was able to find neither an existing algorithm or
stateful unary predicate functor for accomplishing this for a pair of input
iterators. However, I was a bit surprised considering that this seems like a
sequence property query that would tend to come up fairly often and serve a
general utility. Did I just fail to form the proper search/query or am I
overestimating the general utility?
Regardless, I forged ahead with the rather naïve implementation (see below),
which can be used as a predicate with for_each as shown:
const int strictlyIncreasingValues[] = { 1, 2, 3, 4, 5 };
bool isStrictlyIncreasing;
isStrictlyIncreasing = std::for_each(strictlyIncreasingValues,
strictlyIncreasingValues + 5,
is_strictly_increasing<int>());
assert(inStrictlyIncreasing == true);
However, acknowledging the inefficient and naïveté of the first
implementation, this is probably more algorithm than functional in that
for_each with a stateful predicate is wasteful in walking the entire
sequence (i.e. if any arbitrary subsequence fails to meet the property
predicate criteria, the whole sequence fails).
Is a smarter realization of this as an algorithm a potential candidate for
boost::algorithm?
Naïve, inefficient functional implementation to be used with for_each:
#include <functional>
#include <boost/function.hpp>
template <typename T>
struct creasing :
public unary_function<T, bool>
{
protected:
typedef unary_function<T, bool> base_type;
typedef typename base_type::argument_type argument_type;
typedef typename base_type::result_type result_type;
typedef boost::function<result_type (const argument_type &a,
const argument_type &b)>
binary_predicate;
creasing(const binary_predicate & inPredicate) :
base_type(),
mPredicate(inPredicate),
mCreasing(true),
mInited(false),
mLast()
{
return;
}
public:
result_type operator()(const argument_type & x)
{
if (mCreasing) {
if (mInited) {
mCreasing = mPredicate(mLast, x);
} else {
mCreasing = true;
mInited = true;
}
mLast = x;
}
return (mCreasing);
}
operator result_type() const
{
return (mCreasing);
}
private:
const binary_predicate mPredicate;
result_type mCreasing;
result_type mInited;
argument_type mLast;
};
template <typename T>
struct is_increasing :
public creasing<T>
{
typedef creasing<T> base_type;
typedef typename base_type::argument_type argument_type;
is_increasing(void) :
base_type(std::less_equal<argument_type>()) {}
};
template <typename T>
struct is_decreasing :
public creasing<T>
{
typedef creasing<T> base_type;
typedef typename base_type::argument_type argument_type;
is_decreasing(void) :
base_type(std::greater_equal<argument_type>()) {}
};
template <typename T>
struct is_strictly_increasing :
public creasing<T>
{
typedef creasing<T> base_type;
typedef typename base_type::argument_type argument_type;
is_strictly_increasing(void) :
base_type(std::less<argument_type>()) {}
};
template <typename T>
struct is_strictly_decreasing :
public creasing<T>
{
typedef creasing<T> base_type;
typedef typename base_type::argument_type argument_type;
is_strictly_decreasing(void) :
base_type(std::greater<argument_type>()) {}
};
Regards,
Grant
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk