Finally I have written a complete converter. It can convert int to std::string, std::wstring, std::u16string, std::u32string:
#include <string> // std::string, std::wstring
#include <cstdio> // std::sprintf
#include <cwchar> // std::mbstate_t, std::swprintf
#include <climits> // CHAR_BIT
#include <cassert> // assert()
#if __cplusplus >= 201103L
//These will be included if >=C++11 is used
#include <codecvt>
#include <locale> // std::wstring_convert
#endif
template<bool B, typename T = void>
struct EnableIf{};
template<typename T>
struct EnableIf<true, T>{typedef T Type;};
template<typename T1, typename T2>
struct IsSame{ static const bool value = false; };
template<typename T>
struct IsSame<T,T>{ static const bool value = true; };
#if __cplusplus >= 201103L
///Convenience wrapper of std::codecvt (`>=C++11`)
template <class internT, class externT, class stateT>
struct Codecvt : std::codecvt<internT,externT,stateT>
{ ~Codecvt(){} };
///@struct ConvUTF
///`UTF-8 <> UTF-16` and `UTF-8 <> UTF32` converter (`>=C++11`).
template<typename Char_T>
struct ConvUTF { typedef std::wstring_convert<Codecvt<Char_T, char, std::mbstate_t>, Char_T> Converter; };
#endif
///@struct ConvInt
///Contains a function to convert integer to string (either `std::string`
///or `std::wstring` ( or `std::u16string` or `std::u32string` for >=C++11)
///@tparam Char_T Basic character type (`char`, `wchar`, `char16_t`, `char32_t`).
template<typename Char_T, typename T = Char_T> struct ConvInt{};
template<typename Char_T> struct ConvInt<Char_T, typename EnableIf<
IsSame<Char_T, char>::value|IsSame<Char_T, wchar_t>::value, Char_T>::Type>{
//wrapper of sprintf or swprintf
static int mysprint(Char_T*, size_t size, int x);
///Converts an integer to std::string/std::wstring
///@param x the integer to convert
///@return std::string/std::wstring from the integer
static std::basic_string<Char_T> toString(int x){
Char_T buf[sizeof(int)*CHAR_BIT]; //sizeof(int)*CHAR_BIT should always be sufficient
int written = mysprint(buf, sizeof(buf), x);
assert(written > 0);
return std::basic_string<Char_T>(buf);
}
};
template<> inline int ConvInt<char>::mysprint(char* buf, size_t size, int x){
return sprintf(buf, "%d", x);
}
template<> inline int ConvInt<wchar_t>::mysprint(wchar_t* buf, size_t size, int x){
return swprintf(buf, size, L"%d", x);
}
#if __cplusplus >= 201103L
template<typename Char_T> struct ConvInt<Char_T, typename EnableIf<
IsSame<Char_T, char16_t>::value|IsSame<Char_T, char32_t>::value, Char_T>::Type>{
///Converts integer to std::u16string/std::u32string.
///Uses codecvt for conversion.
///@param x int to convert
///@return std::u16string/std::u32string from the integer
static std::basic_string<Char_T> toString(int x){
std::string s = std::to_string(x);
typename ConvUTF<Char_T>::Converter conv;
return conv.from_bytes(s);
}
};
#endif
Usage example:
int main(){
std::cout<<"\nstring: "<<ConvInt<char>::toString(-48);
std::wcout<<"\nwstring: "<<ConvInt<wchar_t>::toString(-2147483647);
#if __cplusplus >= 201103L
ConvUTF<char16_t>::Converter conv;
ConvUTF<char32_t>::Converter conv2;
std::cout<<"\nu16string: "<<conv.to_bytes(ConvInt<char16_t>::toString(-48));
std::cout<<"\nu32string: "<<conv2.to_bytes(ConvInt<char32_t>::toString(-48));
#endif
return 0;
}