Project 3 - Currency Type
currency.hpp
Go to the documentation of this file.
1 
25 #ifndef CURRENCY_HPP_
26 #define CURRENCY_HPP_
27 
28 #include <iomanip>
29 #include <istream>
30 #include <locale>
31 #include <ostream>
32 #include <sstream>
33 #include <string>
34 #include <stdexcept>
35 
36 #include "ioflags.hpp"
37 #include "fixed.hpp"
38 #include "rational.hpp"
39 
41 template<class T=long, int N=2>
42 class currency
43 {
44 public:
45  typedef T int_type;
47 
49  constexpr currency() : value_() {}
52  constexpr currency(T integer) : value_(integer) {}
59  currency(T integer, T fraction) : value_(integer, fraction) {}
62  currency(double value) : value_(value) {}
63 
65  template<class U, int M>
66  currency(currency<U, M> const& rhs): value_(rhs.value()) {}
67 
69  template<class U, int M>
71  {
72  value_ = rhs.value();
73  return *this;
74  }
75 
78  std::string as_string() const;
85  template<class Char, class Traits>
86  bool read(std::basic_istream<Char, Traits>& strm);
87 
90  template<class U>
92  U convert() const { return value().template convert<U>(); }
93 
95  int_type round() const { return value().round(); }
96 
98  int_type integer() const { return value().integer(); }
100  template<int M>
101  int_type fraction() const { return value().template fraction<M>(); }
103  int_type fraction() const { return value().fraction(); }
104 
129 
131  void negate();
132 
134  currency& operator++();
136  currency operator++(int);
138  currency& operator--();
140  currency operator--(int);
141 
143  value_type value() const { return value_; }
144 
145 private:
146  value_type value_;
147 };
148 
149 template<class T, int N>
151 const
152 {
153  std::ostringstream digits;
154  digits.imbue(std::locale::classic());
155  digits << integer() << std::setw(value_type::places) << std::setfill('0') << fraction();
156 
157  std::ostringstream out;
158  std::money_put<char> const& put(std::use_facet<std::money_put<char> >(std::locale()));
159  put.put(std::ostreambuf_iterator<char>(out), false, out, '0', digits.str());
160  return out.str();
161 }
162 
163 template<class T, int N>
165 {
166  value_ += f.value();
167  return *this;
168 }
169 
170 template<class T, int N>
172 {
173  value_ -= f.value();
174  return *this;
175 }
176 
177 template<class T, int N>
179 {
180  value_ *= i;
181  return *this;
182 }
183 template<class T, int N>
185 {
186  value_ *= i;
187  return *this;
188 }
189 
190 template<class T, int N>
192 {
193  value_ /= i;
194  return *this;
195 }
196 template<class T, int N>
198 {
199  value_ /= i;
200  return *this;
201 }
202 
203 template<class T, int N>
205 {
206  value_ = -value_;
207 }
208 
209 template<class T, int N>
211 {
212  ++value_;
213  return *this;
214 }
215 
216 template<class T, int N>
218 {
219  currency result(*this);
220  ++value_;
221  return result;
222 }
223 
224 template<class T, int N>
226 {
227  --value_;
228  return *this;
229 }
230 
231 template<class T, int N>
233 {
234  currency result(*this);
235  --value_;
236  return result;
237 }
238 
239 template<class T, int N>
240 template<class CharT, class Traits>
241 bool currency<T,N>::read(std::basic_istream<CharT,Traits>& strm)
242 {
243  ioflags flags(strm);
244  typename std::basic_istream<CharT, Traits>::sentry sentry(strm, false);
245  if (not sentry)
246  return false;
247 
248  std::ios_base::iostate error(std::ios_base::goodbit);
249  std::string digits;
250  std::money_get<CharT> const& get(
251  std::use_facet<std::money_get<CharT> >(strm.getloc()));
252  get.get(std::istreambuf_iterator<CharT>(strm), std::istreambuf_iterator<CharT>(),
253  false, strm, error, digits);
254 
255  if ((error & std::ios_base::failbit) != 0)
256  return false;
257 
258  std::moneypunct<CharT> const& punct(
259  std::use_facet<std::moneypunct<CharT> >(strm.getloc()));
260 
261  // Set fraction to the rightmost frac_digits() characters of digits.
262  std::string fraction(digits.substr(digits.size() - punct.frac_digits(), punct.frac_digits()));
263  // Set integer to the remainder of digits.
264  std::string integer(digits.substr(0, digits.size() - punct.frac_digits()));
265 
266  std::istringstream fixed_stream(integer + "." + fraction);
267  return value_.read(fixed_stream);
268 }
269 
273 template<class T, int N, class Char, class Traits>
274 std::basic_istream<Char, Traits>& operator>>(std::basic_istream<Char, Traits>& strm, currency<T,N>& c)
275 {
276  if (not c.read(strm))
277  strm.setstate(strm.failbit);
278  return strm;
279 }
280 
284 template<class T, int N, class Char, class Traits>
285 std::basic_ostream<Char, Traits>& operator<<(std::basic_ostream<Char, Traits>& strm, currency<T,N> c)
286 {
287  typename std::basic_ostream<Char, Traits>::sentry sentry(strm);
288  strm << c.as_string();
289  return strm;
290 }
291 
293 template<class T, int N>
295 {
296  a.negate();
297  return a;
298 }
299 
303 template<class T, int N>
305 {
306  a += b;
307  return a;
308 }
309 
313 template<class T, int N>
315 {
316  a -= b;
317  return a;
318 }
319 
323 template<class T, int N>
325 {
326  a *= b;
327  return a;
328 }
329 
333 template<class T, int N>
335 {
336  b *= a;
337  return b;
338 }
339 
343 template<class T, int N>
345 {
346  a /= b;
347  return a;
348 }
349 
353 template<class T, int N>
355 {
356  // Extract the underlying value of the fixed values. No adjustment
357  // to scaling is needed because the numerator and denominator are
358  // both scaled to the same amount.
359  return rational<T>(n.value().value(), d.value().value());
360 }
361 
365 template<class T, int N>
367 {
368  return a.value() == b.value();
369 }
373 template<class T, int N>
375 {
376  return a.value() == b;
377 }
381 template<class T, int N>
383 {
384  return a == b.value();
385 }
386 
390 template<class T, int N>
392 {
393  return not (a == b);
394 }
398 template<class T, int N>
399 inline bool operator!=(currency<T,N> a, T b)
400 {
401  return not (a == b);
402 }
406 template<class T, int N>
407 inline bool operator!=(T a, currency<T,N> b)
408 {
409  return not (a == b);
410 }
411 
415 template<class T, int N>
416 bool operator<(currency<T,N> a, currency<T,N> b)
417 {
418  return a.value() < b.value();
419 }
423 template<class T, int N>
424 bool operator<(currency<T,N> a, T b)
425 {
426  return a.value() < b;
427 }
431 template<class T, int N>
432 bool operator<(T a, currency<T,N> b)
433 {
434  return a < b.value();
435 }
436 
440 template<class T, int N>
442 {
443  return b < a;
444 }
448 template<class T, int N>
449 inline bool operator>(currency<T,N> a, T b)
450 {
451  return b < a;
452 }
456 template<class T, int N>
457 inline bool operator>(T a, currency<T,N> b)
458 {
459  return b < a;
460 }
461 
465 template<class T, int N>
466 inline bool operator<=(currency<T,N> a, currency<T,N> b)
467 {
468  return not (b < a);
469 }
473 template<class T, int N>
474 inline bool operator<=(currency<T,N> a, T b)
475 {
476  return not (b < a);
477 }
481 template<class T, int N>
482 inline bool operator<=(T a, currency<T,N> b)
483 {
484  return not (b < a);
485 }
486 
490 template<class T, int N>
492 {
493  return not (a < b);
494 }
498 template<class T, int N>
499 inline bool operator>=(currency<T,N> a, T b)
500 {
501  return not (a < b);
502 }
506 template<class T, int N>
507 inline bool operator>=(T a, currency<T,N> b)
508 {
509  return not (a < b);
510 }
511 
512 #endif
currency< T, N > operator+(currency< T, N > a, currency< T, N > b)
Definition: currency.hpp:304
currency & operator+=(currency c)
Definition: currency.hpp:164
currency & operator--()
Pre-decrement operator.
Definition: currency.hpp:225
bool read(std::basic_istream< Char, Traits > &strm)
Implement a fixed-point number class template. Values have N places after the decimal point...
Definition: fixed.hpp:26
bool operator==(currency< T, N > a, currency< T, N > b)
Definition: currency.hpp:366
currency< T, N > operator*(currency< T, N > a, T b)
Definition: currency.hpp:324
constexpr currency()
Default constructor initializes the value to zero.
Definition: currency.hpp:49
fixed< T, N > value_type
Type of the actual value.
Definition: currency.hpp:46
value_type value() const
Return the internal value.
Definition: currency.hpp:143
currency< T, N > operator/(currency< T, N > a, T b)
Definition: currency.hpp:344
std::string as_string() const
Definition: currency.hpp:150
Save and restore I/O stream flags.
bool operator!=(currency< T, N > a, currency< T, N > b)
Definition: currency.hpp:391
value_type fraction() const
Return the fractional part, e.g., 3 for 12.03.
Definition: fixed.hpp:129
value_type round() const
Definition: fixed.hpp:204
int_type round() const
Round off to the nearest integer, using banker&#39;s rounding.
Definition: currency.hpp:95
constexpr currency(T integer)
Definition: currency.hpp:52
Represent a rational number (fraction) as a numerator and denominator.
Definition: rational.hpp:16
void negate()
Negate this value.
Definition: currency.hpp:204
currency(currency< U, M > const &rhs)
Copy a value that uses a different precision.
Definition: currency.hpp:66
currency & operator=(currency< U, M > rhs)
Assign a value that uses a different precision.
Definition: currency.hpp:70
currency & operator*=(value_type m)
Definition: currency.hpp:178
bool operator>=(currency< T, N > a, currency< T, N > b)
Definition: currency.hpp:491
currency & operator-=(currency c)
Definition: currency.hpp:171
currency(double value)
Definition: currency.hpp:62
currency(T integer, T fraction)
Definition: currency.hpp:59
int_type integer() const
Return the integer part (which is the same as trunc()).
Definition: currency.hpp:98
int_type fraction() const
Return the fractional part, to M places.
Definition: currency.hpp:101
currency & operator++()
Pre-increment operator.
Definition: currency.hpp:210
value_type integer() const
Return the integer part (which is the same as trunc()).
Definition: fixed.hpp:71
value_type value() const
Return the internal value.
Definition: fixed.hpp:97
bool operator>(currency< T, N > a, currency< T, N > b)
Definition: currency.hpp:441
int_type fraction() const
Return the fractional part.
Definition: currency.hpp:103
U convert() const
Convert to some other type, especially floating point.
Definition: currency.hpp:92
std::basic_istream< Char, Traits > & operator>>(std::basic_istream< Char, Traits > &strm, currency< T, N > &c)
Definition: currency.hpp:274
currency & operator/=(value_type m)
Definition: currency.hpp:191
T int_type
Storage type.
Definition: currency.hpp:45
currency< T, N > operator-(currency< T, N > a)
Negate a currency value.
Definition: currency.hpp:294