|
||||
|
Section 39:
|
[39.3] Can I templatize the above functions so they work with other types?
Yes — for any types that support iostream-style input/output. For example, suppose you want to convert an object of class Foo to a std::string, or perhaps the reverse: from a std::string to a Foo. You could write a whole family of conversion functions based on the ones shown in the previous FAQs, or you could write a template function so the compiler does the grunt work. For example, to convert an arbitrary type T to a std::string, provided T supports syntax like std::cout << x, you can use this:
// File: convert.h
#include <iostream>
#include <sstream>
#include <string>
#include <typeinfo>
#include <stdexcept>
class BadConversion : public std::runtime_error {
public:
BadConversion(std::string const& s)
: std::runtime_error(s)
{ }
};
template<typename T>
inline std::string stringify(T const& x)
{
std::ostringstream o;
if (!(o << x))
throw BadConversion(std::string("stringify(")
+ typeid(x).name() + ")");
return o.str();
}
Here's how to use the stringify() function:
#include "convert.h"
void myCode()
{
Foo x;
...
std::string s = "this is a Foo: " + stringify(x);
...
}
You can also convert from any type that supports iostream
input by adding this to file convert.h:
template<typename T>
inline void convert(std::string const& s, T& x,
bool failIfLeftoverChars = true)
{
std::istringstream i(s);
char c;
if (!(i >> x) || (failIfLeftoverChars && i.get(c)))
throw BadConversion(s);
}
Here's how to use the convert() function:
#include "convert.h"
void myCode()
{
std::string s = ...a string representation of a Foo...;
...
Foo x;
convert(s, x);
...
...code that uses x...
}
To simplify your code, particularly for light-weight easy-to-copy types, you
probably want to add a return-by-value conversion function to file
convert.h:
template<typename T>
inline T convertTo(std::string const& s,
bool failIfLeftoverChars = true)
{
T x;
convert(s, x, failIfLeftoverChars);
return x;
}
This simplifies your "usage" code some. You call it by explicitly specifying
the template parameter T:
#include "convert.h"
void myCode()
{
std::string a = ...string representation of an int...;
std::string b = ...string representation of an int...;
...
if (convertTo<int>(a) < convertTo<int>(b))
...;
}
|
|||