Listing 5 Temperature.cpp (alt)
// My header
#include "Temperature.h"
#include <ostream>
#include <istream>
#include <stdexcept>
namespace Util {
// iword / pword index
const int Temperature::strm_index =
std::ios::xalloc();
// Facet id
std::locale::id Temperature::punct::id;
// static facets
Temperature::punct Temperature::punct_asK(&Temperature::inK, 'K');
Temperature::punct Temperature::punct_asC(&Temperature::inC, 'C');
Temperature::punct Temperature::punct_asF(&Temperature::inF, 'F');
// manipulators
std::ostream&
Temperature::asK(std::ostream& os)
{
os.pword(strm_index) = &punct_asK;
return os;
};
std::ostream&
Temperature::asC(std::ostream& os)
{
os.pword(strm_index) = &punct_asC;
return os;
};
std::ostream&
Temperature::asF(std::ostream& os)
{
os.pword(strm_index) = &punct_asF;
return os;
};
std::ostream&
Temperature::showscale(std::ostream& os)
{
os.iword(strm_index) = 1;
return os;
};
std::ostream&
Temperature::noscale(std::ostream& os)
{
os.iword(strm_index) = 0;
return os;
};
// ostream inserter
std::ostream&
operator<<(std::ostream& os, Temperature obj)
{
int idx = Temperature::strm_index;
const Temperature::punct* fac =
reinterpret_cast<Temperature::punct*>(os.pword(idx));
if (not fac) {
std::locale loc = os.getloc();
bool found = std::has_facet<Temperature::punct>(loc);
if (not found) {
os.setstate(std::ios::failbit); // may throw exception
return os;
}
fac = &std::use_facet<Temperature::punct>(loc);
}
bool show_scale = os.iword(idx) bitand 1;
int width = os.width();
if (show_scale and width > 0)
os.width(width-1);
os << fac->value(obj);
if (show_scale) os << fac->scale();
return os;
}
// istream extractor
std::istream&
operator>>(std::istream& is, Temperature& obj)
{
// Assumed to be in format 'nn.nX' where 'X' is F/C/K
// Read the number
float val = -1.0;
is >> val;
// Get next character
int ch = is.get();
switch (char(ch)) {
case 'F':
obj = Temperature::inF(val);
break;
case 'C':
obj = Temperature::inC(val);
break;
case 'K':
obj = Temperature::inK(val);
break;
default:
is.setstate(std::ios::failbit); // may throw exception
obj = Temperature::inK(-1.0);
}
return is;
}
} //> namespace