Search code examples
c++templatesc++14partial-specialization

Implement `to_xstring()` to unite `to_string()` and `to_wstring()`


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);
}

Solution

  • 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);
    }