Boost.TypeErasure — Counter
#include <cassert>
#include <iostream>
#include <boost/type_erasure/any.hpp>
#include <boost/type_erasure/operators.hpp> // decrementable
#include <boost/concept_check.hpp>
#include <boost/mpl/vector.hpp>
// (1) Concept, for compile-time tests
template <typename C>
struct CountdownCounter : boost::Assignable<C>
, boost::CopyConstructible<C>
{
BOOST_CONCEPT_USAGE(CountdownCounter)
{
--c;
(bool(c));
bool b = !c;
(bool(--c));
}
private:
C c;
};
// (2) Mini-concept for contextual conversion to bool
template <class T>
struct testable
{
static bool apply(const T& arg) { return bool(arg); }
};
// (3) Teaching framework the conversion to bool
namespace boost { namespace type_erasure {
template<class T, class Base>
struct concept_interface <testable<T>, Base, T> : Base
{
explicit operator bool () const
{ return call(testable<T>(), *this); }
};
}}
using boost::type_erasure::decrementable;
namespace te = boost::type_erasure;
// (4) Composing the interface functions
using Counter = boost::mpl::vector<
te::copy_constructible<>,
decrementable<>,
testable<te::_self>,
te::relaxed
>;
// (5) The type-erased interface
using AnyCounter = te::any<Counter>;
// (6) Custom Counter for tests
struct LoggingCounter
{
int c = 2;
explicit operator bool () const { return c; }
LoggingCounter& operator--()
{
std::cout << "decremented\n";
--c;
return *this;
}
};
// (7) Compile-time test
BOOST_CONCEPT_ASSERT((CountdownCounter<int>));
BOOST_CONCEPT_ASSERT((CountdownCounter<LoggingCounter>));
BOOST_CONCEPT_ASSERT((CountdownCounter<AnyCounter>));
// (8) Run-time test
void test_counter()
{
AnyCounter counter1 = 2; // bind to int (initially 2)
assert (counter1); // still counting
assert (--counter1); // still counting (1)
AnyCounter counter2 = counter1;
// counter2 (int) counts from 1
--counter1;
assert (!counter1); // done
assert (counter2); // counter2 still 1
assert (!--counter2); // counter2 also done
counter1 = LoggingCounter{};
// reset with a different type
assert (counter1); // 2
--counter1;
assert (counter1); // 1
--counter1;
assert (!counter1); // 0
}
int main ()
{
test_counter();
}
Like this:
Like Loading...