- Main Page
- Classes
- Files

# currency.hpp

Go to the documentation of this file.

    00001
    00005 #ifndef CURRENCY_HPP_
    00006 #define CURRENCY_HPP_
    00007
    00008 #include <iomanip>
    00009 #include <istream>
    00010 #include <locale>
    00011 #include <ostream>
    00012 #include <sstream>
    00013 #include <string>
    00014 #include <stdexcept>
    00015
    00016 #include "ioflags.hpp"
    00017 #include "fixed.hpp"
    00018 #include "rational.hpp"
    00019
    00021 template<class T=long, int N=2>
    00022 class currency
    00023 {
    00024 public:
    00025   typedef T int_type;
    00026   typedef fixed<T,N> value_type;
    00027
    00029   currency() : value_() {}
    00032   currency(T integer) : value_(integer) {}
    00039   currency(T integer, T fraction) : value_(integer, fraction) {}
    00042   currency(double value) : value_(value) {}
    00043
    00045   template<class U, int M>
    00046   currency(currency<U, M> const& rhs): value_(rhs.value()) {}
    00047
    00049   template<class U, int M>
    00050   currency& operator=(currency<U, M> rhs)
    00051   {
    00052     value_ = rhs.value();
    00053     return *this;
    00054   }
    00055
    00058   std::string as_string() const;
    00065   template<class Char, class Traits>
    00066   bool read(std::basic_istream<Char, Traits>& strm);
    00067
    00070   template<class U>
    00072   U convert() const { return value().convert<U>(); }
    00073
    00075   int_type round() const { return value().round(); }
    00076
    00078   int_type integer()  const { return value().integer(); }
    00080   template<int M>
    00081   int_type fraction() const { return value().fraction<M>(); }
    00083   int_type fraction() const { return value().fraction(); }
    00084
    00088   currency& operator+=(currency c);
    00092   currency& operator-=(currency c);
    00096   currency& operator*=(value_type m);
    00100   currency& operator*=(int_type m);
    00104   currency& operator/=(value_type m);
    00108   currency& operator/=(int_type m);
    00109
    00111   void negate();
    00112
    00114   currency& operator++();
    00116   currency operator++(int);
    00118   currency& operator--();
    00120   currency operator--(int);
    00121
    00123   value_type value()    const { return value_; }
    00124
    00125 private:
    00126   value_type value_;
    00127 };
    00128
    00129 template<class T, int N>
    00130 std::string currency<T,N>::as_string()
    00131 const
    00132 {
    00133   std::ostringstream digits;
    00134   digits.imbue(std::locale::classic());
    00135   digits << integer() << std::setw(value_type::places) << std::setfill('0') << fraction();
    00136
    00137   std::ostringstream out;
    00138   std::money_put<char> const& put(std::use_facet<std::money_put<char> >(std::locale()));
    00139   put.put(std::ostreambuf_iterator<char>(out), false, out, '0', digits.str());
    00140   return out.str();
    00141 }
    00142
    00143 template<class T, int N>
    00144 currency<T,N>& currency<T,N>::operator+=(currency f)
    00145 {
    00146   value_ += f.value();
    00147   return *this;
    00148 }
    00149
    00150 template<class T, int N>
    00151 currency<T,N>& currency<T,N>::operator-=(currency f)
    00152 {
    00153   value_ -= f.value();
    00154   return *this;
    00155 }
    00156
    00157 template<class T, int N>
    00158 currency<T,N>& currency<T,N>::operator*=(value_type i)
    00159 {
    00160   value_ *= i;
    00161   return *this;
    00162 }
    00163 template<class T, int N>
    00164 currency<T,N>& currency<T,N>::operator*=(int_type i)
    00165 {
    00166   value_ *= i;
    00167   return *this;
    00168 }
    00169
    00170 template<class T, int N>
    00171 currency<T,N>& currency<T,N>::operator/=(value_type i)
    00172 {
    00173   value_ /= i;
    00174   return *this;
    00175 }
    00176 template<class T, int N>
    00177 currency<T,N>& currency<T,N>::operator/=(int_type i)
    00178 {
    00179   value_ /= i;
    00180   return *this;
    00181 }
    00182
    00183 template<class T, int N>
    00184 void currency<T,N>::negate()
    00185 {
    00186   value_ = -value_;
    00187 }
    00188
    00189 template<class T, int N>
    00190 currency<T,N>& currency<T,N>::operator++()
    00191 {
    00192   ++value_;
    00193   return *this;
    00194 }
    00195
    00196 template<class T, int N>
    00197 currency<T,N> currency<T,N>::operator++(int)
    00198 {
    00199   currency result(*this);
    00200   ++value_;
    00201   return result;
    00202 }
    00203
    00204 template<class T, int N>
    00205 currency<T,N>& currency<T,N>::operator--()
    00206 {
    00207   --value_;
    00208   return *this;
    00209 }
    00210
    00211 template<class T, int N>
    00212 currency<T,N> currency<T,N>::operator--(int)
    00213 {
    00214   currency result(*this);
    00215   --value_;
    00216   return result;
    00217 }
    00218
    00219 template<class T, int N>
    00220 template<class CharT, class Traits>
    00221 bool currency<T,N>::read(std::basic_istream<CharT,Traits>& strm)
    00222 {
    00223   ioflags flags(strm);
    00224   typename std::basic_istream<CharT, Traits>::sentry sentry(strm, false);
    00225   if (not sentry)
    00226     return false;
    00227
    00228   std::ios_base::iostate error(std::ios_base::goodbit);
    00229   std::string digits;
    00230   std::money_get<CharT> const& get(
    00231       std::use_facet<std::money_get<CharT> >(strm.getloc()));
    00232   get.get(std::istreambuf_iterator<CharT>(strm), std::istreambuf_iterator<CharT>(),
    00233           false, strm, error, digits);
    00234
    00235   if ((error & std::ios_base::failbit) != 0)
    00236     return false;
    00237
    00238   std::moneypunct<CharT> const& punct(
    00239       std::use_facet<std::moneypunct<CharT> >(strm.getloc()));
    00240
    00241   // Set fraction to the rightmost frac_digits() characters of digits.
    00242   std::string fraction(digits.substr(digits.size() - punct.frac_digits(), punct.frac_digits()));
    00243   // Set integer to the remainder of digits.
    00244   std::string integer(digits.substr(0, digits.size() - punct.frac_digits()));
    00245
    00246   std::istringstream fixed_stream(integer + "." + fraction);
    00247   return value_.read(fixed_stream);
    00248 }
    00249
    00253 template<class T, int N, class Char, class Traits>
    00254 std::basic_istream<Char, Traits>& operator>>(std::basic_istream<Char, Traits>& strm, currency<T,N>& c)
    00255 {
    00256   if (not c.read(strm))
    00257     strm.setstate(strm.failbit);
    00258   return strm;
    00259 }
    00260
    00264 template<class T, int N, class Char, class Traits>
    00265 std::basic_ostream<Char, Traits>& operator<<(std::basic_ostream<Char, Traits>& strm, currency<T,N> c)
    00266 {
    00267   typename std::basic_ostream<Char, Traits>::sentry sentry(strm);
    00268   strm << c.as_string();
    00269   return strm;
    00270 }
    00271
    00273 template<class T, int N>
    00274 currency<T,N> operator-(currency<T,N> a)
    00275 {
    00276   a.negate();
    00277   return a;
    00278 }
    00279
    00283 template<class T, int N>
    00284 currency<T,N> operator+(currency<T,N> a, currency<T,N> b)
    00285 {
    00286   a += b;
    00287   return a;
    00288 }
    00289
    00293 template<class T, int N>
    00294 currency<T,N> operator-(currency<T,N> a, currency<T,N> b)
    00295 {
    00296   a -= b;
    00297   return a;
    00298 }
    00299
    00303 template<class T, int N>
    00304 currency<T,N> operator*(currency<T,N> a, T b)
    00305 {
    00306   a *= b;
    00307   return a;
    00308 }
    00309
    00313 template<class T, int N>
    00314 currency<T,N> operator*(T a, currency<T,N> b)
    00315 {
    00316   b *= a;
    00317   return b;
    00318 }
    00319
    00323 template<class T, int N>
    00324 currency<T,N> operator/(currency<T,N> a, T b)
    00325 {
    00326   a /= b;
    00327   return a;
    00328 }
    00329
    00333 template<class T, int N>
    00334 rational<T> operator/(currency<T,N> n, currency<T,N> d)
    00335 {
    00336   // Extract the underlying value of the fixed values. No adjustment
    00337   // to scaling is needed because the numerator and denominator are
    00338   // both scaled to the same amount.
    00339   return rational<T>(n.value().value(), d.value().value());
    00340 }
    00341
    00345 template<class T, int N>
    00346 bool operator==(currency<T,N> a, currency<T,N> b)
    00347 {
    00348   return a.value() == b.value();
    00349 }
    00353 template<class T, int N>
    00354 bool operator==(currency<T,N> a, T b)
    00355 {
    00356   return a.value() == b;
    00357 }
    00361 template<class T, int N>
    00362 bool operator==(T a, currency<T,N> b)
    00363 {
    00364   return a == b.value();
    00365 }
    00366
    00370 template<class T, int N>
    00371 inline bool operator!=(currency<T,N> a, currency<T,N> b)
    00372 {
    00373   return not (a == b);
    00374 }
    00378 template<class T, int N>
    00379 inline bool operator!=(currency<T,N> a, T b)
    00380 {
    00381   return not (a == b);
    00382 }
    00386 template<class T, int N>
    00387 inline bool operator!=(T a, currency<T,N> b)
    00388 {
    00389   return not (a == b);
    00390 }
    00391
    00395 template<class T, int N>
    00396 bool operator<(currency<T,N> a, currency<T,N> b)
    00397 {
    00398   return a.value() < b.value();
    00399 }
    00403 template<class T, int N>
    00404 bool operator<(currency<T,N> a, T b)
    00405 {
    00406   return a.value() < b;
    00407 }
    00411 template<class T, int N>
    00412 bool operator<(T a, currency<T,N> b)
    00413 {
    00414   return a < b.value();
    00415 }
    00416
    00420 template<class T, int N>
    00421 inline bool operator>(currency<T,N> a, currency<T,N> b)
    00422 {
    00423   return b < a;
    00424 }
    00428 template<class T, int N>
    00429 inline bool operator>(currency<T,N> a, T b)
    00430 {
    00431   return b < a;
    00432 }
    00436 template<class T, int N>
    00437 inline bool operator>(T a, currency<T,N> b)
    00438 {
    00439   return b < a;
    00440 }
    00441
    00445 template<class T, int N>
    00446 inline bool operator<=(currency<T,N> a, currency<T,N> b)
    00447 {
    00448   return not (b < a);
    00449 }
    00453 template<class T, int N>
    00454 inline bool operator<=(currency<T,N> a, T b)
    00455 {
    00456   return not (b < a);
    00457 }
    00461 template<class T, int N>
    00462 inline bool operator<=(T a, currency<T,N> b)
    00463 {
    00464   return not (b < a);
    00465 }
    00466
    00470 template<class T, int N>
    00471 inline bool operator>=(currency<T,N> a, currency<T,N> b)
    00472 {
    00473   return not (a < b);
    00474 }
    00478 template<class T, int N>
    00479 inline bool operator>=(currency<T,N> a, T b)
    00480 {
    00481   return not (a < b);
    00482 }
    00486 template<class T, int N>
    00487 inline bool operator>=(T a, currency<T,N> b)
    00488 {
    00489   return not (a < b);
    00490 }
    00491
    00492 #endif