Adobe.Poly — Counter
#include <cassert>
#include <iostream>
#include <adobe/poly.hpp>
#include <boost/concept_check.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) The inner interface
struct CounterIface : adobe::poly_copyable_interface
{
virtual void decrement() = 0;
virtual bool done() const = 0;
};
// (3) The inner interface implementation
template <typename T>
struct CounterImpl
: adobe::optimized_storage_type<T, CounterIface>::type
{
using base_t = typename
adobe::optimized_storage_type<T, CounterIface>::type;
BOOST_CONCEPT_ASSERT((CountdownCounter<T>));
CounterImpl(T x) : base_t(x) {}
CounterImpl(adobe::move_from<CounterImpl> x)
: base_t(adobe::move_from<base_t>(x.source)) {}
void decrement() override { --this->get(); }
bool done() const override { return bool(this->get()); }
};
// (4) The outer interface specification
struct Counter : adobe::poly_base<CounterIface, CounterImpl>
{
using base_t = adobe::poly_base<CounterIface, CounterImpl>;
using base_t::base_t; // Inherit constructors
Counter(adobe::move_from<Counter> x)
: base_t(adobe::move_from<base_t>(x.source)) {}
Counter& operator--()
{
interface_ref().decrement();
return *this;
}
explicit operator bool() const
{
return interface_ref().done();
}
};
// (5) The interface
typedef adobe::poly<Counter> AnyCounter;
// (6) Another counter for testing
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 = AnyCounter{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...
bells and whistles