/*
* ===========================================================================
* Clock Application (and tests)
* ===========================================================================
*/
#include <iostream>
#include <iomanip>
#include "clock.h"
#include "counter.h"
#ifdef TDD
void basic_counter_test() {
my::BaseCounter hh{24};
my::ChainCounter mm{60, hh};
my::ChainCounter ss{60, mm};
hh.set_value(6);
mm.set_value(59);
ss.set_value(57);
for (int i = 0; i < 5; ++ i) {
std::cout << hh << " | " << mm << " | " << ss << std::endl;
ss.incr();
}
}
int main() {
basic_counter_test();
}
#else
int main() {
std::cout << "??? clock application ???" << std::endl;
}
#endif
# 2_Clock Step 0 (action items)
## Review the code
Note the questions you have.
## Complete the code at the points marked "<--- TBD"
Obviously in the test main program two `ChainCounter`-s are
connected into a 24 hour clock and the tests programmed so far
appear to check whether an overflow from `mm` is transferred
into `hh`. If you guessed the "TBD" parts correctly the output
should acually show this behavior.
# 2_Clock Step 0 (read first)
File | Syntax | Content
------------|--------|---------------------------------
main.cpp | C++14 | some source code
counter.h | C++14 | `counter` module header file
counter.cpp | C++14 | `counter` module implementation
clock.h | C++14 | `clock` module header file
clock.cpp | C++14 | `clock` module implementation
Makefile | make | build instructions
**NOTE**:\
Some files are still empty and only serve as placeholders.
/* Module Header
* ============================================================================
* Chainable Counter Class
* ============================================================================
*/
#ifndef COUNTER_H_
#define COUNTER_H_
#include <iosfwd> // suffices as only references to iostreams are used
#include <limits> // this is NOT `<climits>` (neither `<limits.h>`)
namespace my {
class BaseCounter {
public:
using value_type = int;
BaseCounter(value_type limit)
: limit_{limit}
, value_{}
{ /*empty*/ }
auto set_value(value_type const value) {
value_ = value;
}
auto get_value() const {
return value_;
}
auto get_limit() const {
return limit_;
}
virtual void incr() {
if (++value_ >= limit_) {
value_ = value_type{};
}
}
private:
value_type limit_{std::numeric_limits<value_type>::max()};
value_type value_{};
};
class ChainCounter : public BaseCounter {
public:
ChainCounter(value_type limit, BaseCounter& next)
: BaseCounter(limit)
, next_{next}
{ /*empty*/ }
virtual void incr() override {
BaseCounter::incr();
if (get_value() == 0) {
next_.incr();
}
}
private:
BaseCounter& next_;
}; // class
} // namespace
std::ostream& operator<<(std::ostream&, my::BaseCounter const&);
#endif // guard
/* Module Implementation
* ============================================================================
* Chainable Counter Class
* ============================================================================
*/
#include "counter.h" // own header file ALWAYS FIRST
#include <iostream> // `<ios_fwd>` not any longer suffices
#include <iomanip> // for `std::setw`
namespace my {
} // namespace
std::ostream& operator<<(std::ostream& lhs,
my::BaseCounter const& rhs) {
std::ostream s{std::cout.rdbuf()};
s.fill('0');
s << "value=" << std::setw(2) << rhs.get_value() << ", "
"limit=" << std::setw(2) << rhs.get_limit();
return lhs;
// return lhs << "value=" << rhs.get_value() << ", "
// "limit=" << rhs.get_limit();
}
// PREPARED BUT NOT YET USED
#ifndef CLOCK_H_
#define CLOCK_H_
namespace my {
} // namespace
#endif // guard
// PREPARED BUT NOT YET USED
#include "clock.h"
namespace my {
} // namespace