Skip to main content
added 19 characters in body
Source Link
Jahid
  • 163
  • 1
  • 7

FinallyNow I have written a complete converter. Itit so that it can convert int to std::string, std::wstring, (and to std::u16string, std::u32string when >=C++11 is being used):

Finally I have written a complete converter. It can convert int to std::string, std::wstring, std::u16string, std::u32string:

Now I have written it so that it can convert int to std::string, std::wstring (and to std::u16string, std::u32string when >=C++11 is being used):

Source Link
Jahid
  • 163
  • 1
  • 7

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