Since the names of to_string()
and to_wstring()
differ, it's practically impossible to use them in generic functions. So, I'm planning to unite them with the following:
template <typename CharT, typename T>
auto to_xstring(const T& x);
The question is how to implement such a function template succinctly.
My current implementation is somewhat clumsy (with a detail
namespace even). Since C++ does not allow partial specialization of function templates, I have the function template dispatch to structs that can be partial specialized. I'm looking for a better implementation.
namespace detail {
template <typename>
struct to_xstring_helper;
template <>
struct to_xstring_helper<char> {
template <typename T>
static std::string invoke(const T& x) {
// explicitly pulls in `std` in case `T` is not a class type
using std::to_string;
return to_string(x);
}
};
template <>
struct to_xstring_helper<wchar_t> {
template <typename T>
static std::wstring invoke(const T& x) {
// explicitly pulls in `std` in case `T` is not a class type
using std::to_wstring;
return to_wstring(x);
}
};
} // namespace detail
/// Calls either `to_string(x)` or `to_wstring(x)` based on `CharT`. Lookups in
/// namespace `std` and that of `T` (by ADL). Given a uniform name, this
/// function template facilitates writing generic functions.
template <typename CharT, typename T>
auto to_xstring(const T& x) {
return detail::to_xstring_helper<CharT>::invoke(x);
}
You could use SFINAE for this, no? E.g., using std::enable_if
:
template <typename CharT, typename T>
typename std::enable_if<std::is_same<CharT, char>::value, std::string>::type
to_xstring(const T &t)
{
return std::to_string(t);
}
template <typename CharT, typename T>
typename std::enable_if<!std::is_same<CharT, char>::value, std::wstring>::type
to_xstring(const T &t)
{
return std::to_wstring(t);
}