I'm a game programmer, plenty of IDs maybe typed as unsigned
int
are very common in my game code; and in some context, I'd like to convert a numeric ID into
string
or parse it back from a
string
; such conversions often go with ID operations together. I hated conversions everywhere, so I decided to make an ID tool class as below:
template<typename T>
class AutoId {
public:
AutoId() {
mNum = T(0);
mStr = "";
mNumDirty = false;
mStrDirty = true;
}
AutoId(T n) {
mNum = n;
mNumDirty = false;
mStrDirty = true;
}
AutoId(const std::string &s) {
mStr = s;
mStrDirty = false;
mNumDirty = true;
}
AutoId(const AutoId<T> &other) {
mNum = other.mNum;
mStr = other.mStr;
mNumDirty = other.mNumDirty;
mStrDirty = other.mStrDirty;
}
~AutoId() {
}
AutoId<T> &operator = (const AutoId<T> &other) {
mNum = other.mNum;
mStr = other.mStr;
mNumDirty = other.mNumDirty;
mStrDirty = other.mStrDirty;
return this;
}
AutoId<T> &operator = (T n) { mNum = n;
mNumDirty = false;
mStrDirty = true;
return *this;
}
AutoId<T> &operator = (const std::string &s) { mStr = s;
mStrDirty = false;
mNumDirty = true;
return *this;
}
operator T(void) { if(mNumDirty) {
assert(!mStrDirty);
std::istringstream ss(mStr);
ss >> mNum;
mNumDirty = false;
}
return mNum;
}
operator std::string(void) { if(mStrDirty) {
assert(!mNumDirty);
std::ostringstream ss;
ss << mNum;
mStr = ss.str();
mStrDirty = false;
}
return mStr;
}
private:
T mNum;
std::string mStr;
bool mNumDirty;
bool mStrDirty;
};
The recipe is those operator overloadings. The guard variables
mNumDirty
and
mStrDirty
keep that conversions will occur when it is really necessary. To use this code, you may just get or set either type
string
or numbers like:
AutoId<int> id1(5);
AutoId<float> id2("3.14");
AutoId<unsigned int> id3; id3 = 400;
AutoId<double> id4; id4 = "5423.234236";
int nid1 = id1;
std::string sid1 = id1;
float nid2 = id2;
std::string sid2 = id2;
unsigned int nid3 = id3;
std::string sid3 = id3;
double nid4 = id4;
std::string sid4 = id4;
Hope this helps if you need it. Any suggestions are appreciated.