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

Generated on Sun Nov 30 10:03:13 2008 for Project 3 - Currency Type by  doxygen 1.5.3