locked
Convert integer to string RRS feed

  • Question

  • Visual Studio 2019 16.1.3, VC++, Win 7 SP1 Pro.

    I have in my h file:

    using string_t = std::basic_string<TCHAR>;
    using sstream_t = std::basic_stringstream<TCHAR>;
    

    To convert some integer n  to string_t I am using

    sstram_t stream_t;
    
    int n = 2;
    
    stream_t << n << std::endl;;
    
    string_t rees_str = stream_t.str();
    
    
    

    All is working fine.

    But is there more elegant and short wau to do that?

    Monday, June 24, 2019 11:27 PM

All replies

  • Like:

    #include <string>
    
    int main()
    {
    	std::string s = std::to_string(2);
    
    	return 0;
    }

    for example?


    This is a signature. Any samples given are not meant to have error checking or show best practices. They are meant to just illustrate a point. I may also give inefficient code or introduce some problems to discourage copy/paste coding. This is because the major point of my posts is to aid in the learning process.

    Monday, June 24, 2019 11:37 PM
  • If you want this in a character set independent way, annoyingly there is nothing as convenient as the typedef for calling a function. To do this in the most compact way would require partial template function specialisation and that doesn't exist in C++.

    The next best method would mean that you will have to write a one off set of template classes/structures to do this, but it should only be something like:

    #include <Windows.h>
    #include <string>
    
    template<typename T>
    struct to_tstring_forwarder;
    
    template<>
    struct to_tstring_forwarder<char>
    {
    	template<typename U>
    	static std::basic_string<char> to_tstring(U arg)
    	{
    		return std::to_string(arg);
    	}
    };
    
    template<>
    struct to_tstring_forwarder<wchar_t>
    {
    	template<typename U>
    	static std::basic_string<wchar_t> to_tstring(U arg)
    	{
    		return std::to_wstring(arg);
    	}
    };
    
    template<typename T, typename U>
    std::basic_string<T> to_tstring(U arg)
    {
    	return to_tstring_forwarder<T>::to_tstring(arg);
    }
    
    using cvt = to_tstring_forwarder<TCHAR>;
    
    int main()
    {
    	std::basic_string<TCHAR> s = cvt::to_tstring(1);
    	std::basic_string<TCHAR> t = to_tstring<TCHAR>(1);
    
    	return 0;
    }

    I included both ways of calling it here. Once this is defined, you can either call it using the typedef or using the template parameter.

    Unfortunately you need to use one of these two ways, since you are specialising on the return type so the compiler can't deduce this.


    This is a signature. Any samples given are not meant to have error checking or show best practices. They are meant to just illustrate a point. I may also give inefficient code or introduce some problems to discourage copy/paste coding. This is because the major point of my posts is to aid in the learning process.

    • Edited by Darran Rowe Tuesday, June 25, 2019 12:30 AM
    Monday, June 24, 2019 11:58 PM
  • This does not work. The to_string converts int to string, bsic_string<char>. There is variant to_wstring, to basic_string<wchar>. No one does not convert to basic_string<_TCHAR>.

    Of course, under Windows we can live with wstring...

    Monday, June 24, 2019 11:59 PM
  • This does not work. The to_string converts int to string, bsic_string<char>. There is variant to_wstring, to basic_string<wchar>. No one does not convert to basic_string<_TCHAR>.

    Of course, under Windows we can live with wstring...

    TCHAR is a macro for char or wchar_t. It depends if you compile your Project in UNICODE or not.

    https://www.codeproject.com/Articles/76252/What-are-TCHAR-WCHAR-LPSTR-LPWSTR-LPCTSTR-etc

    You say that to_string converts to char. So you compile in Multi-Byte character set. Then TCHAR is char.

    You must explain what you mean by "this does not work".

    Regards, Guido

    Tuesday, June 25, 2019 6:01 AM
  • I don't think he saw my follow up post.

    This is a signature. Any samples given are not meant to have error checking or show best practices. They are meant to just illustrate a point. I may also give inefficient code or introduce some problems to discourage copy/paste coding. This is because the major point of my posts is to aid in the learning process.

    Tuesday, June 25, 2019 5:09 PM
  • My project is in UNICODE. to_string does not work because the VS 2019 compiler does not know how to convert string to string of _TCHAR.
    Tuesday, June 25, 2019 11:37 PM
  • Thank for reply.

    Of course we can go your way, Is it the simplest?

    I see the function with only two lines:

    using string_t = std::basic_string<TCHAR>;
    using sstream_t = std::basic_stringstream<TCHAR>;
    
    template <typename T>
    string_t to_string(T n)
    {
      sstream_t stream_t << n << std::endl;
      return stream_t.str();
    }

    It will work with all types of POD types, but I do not like to open streams etc.

    I hoped to learn some simpler way

    Tuesday, June 25, 2019 11:53 PM
  • That function gives me a compiler error. Also the std::endl is a terrible idea. If you want the new line then use TEXT("\n"). std::endl does a flush on the stream and this kills performace.

    Anyway, the whole thing with my version is that it optimises much better.

    If we do some testing:

    int main()
    {
    	LARGE_INTEGER freq;
    	QueryPerformanceFrequency(&freq);
    	LARGE_INTEGER start1, end1;
    	QueryPerformanceCounter(&start1);
    	for (int i = 0; i < 10'000; ++i)
    	{
    		std::basic_string<TCHAR> s = to_string(1);
    		std::wcout << s << L"\n";
    	}
    	QueryPerformanceCounter(&end1);
    
    	LARGE_INTEGER start2, end2;
    	QueryPerformanceCounter(&start2);
    	for (int i = 0; i < 10'000; ++i)
    	{
    		std::basic_string<TCHAR> s = to_tstring<TCHAR>(1);
    		std::wcout << s << L"\n";
    	}
    	QueryPerformanceCounter(&end2);
    
    	std::wcout << L"to_string\n";
    	std::wcout << ((end1.QuadPart - start1.QuadPart) * 1'000) / freq.QuadPart << L"ms\n";
    	std::wcout << L"to_tstring\n";
    	std::wcout << ((end2.QuadPart - start2.QuadPart) * 1'000) / freq.QuadPart << L"ms\n";
    
    	return 0;
    }

    Where to_string is your to_string function without the << std::endl:

    template<typename T>
    inline string_t to_string(T n)
    {
    	sstream_t stream_t;
    	//this went on a separate line due to compiler errors
    	stream_t << n;
    	return stream_t.str();
    }

    and to_tstring is my to_tstring as I already gave it. The results that I get are:

    to_string
    10801ms
    to_tstring
    950ms

    This is in milliseconds. So over several runs to_tstring hovers around 1 second where to_string hovers around 9.5 seconds.

    So this may not be the simplest in terms of lines of code, but it is the best since it only really calls one function.


    This is a signature. Any samples given are not meant to have error checking or show best practices. They are meant to just illustrate a point. I may also give inefficient code or introduce some problems to discourage copy/paste coding. This is because the major point of my posts is to aid in the learning process.

    Wednesday, June 26, 2019 2:26 AM
  • >10801ms - this is why I did not like it. Of course if you have 20 conversions in the ntire project...

    > Compiler error - what kind?

    Anyway. thank you. I marked your last post as an answer.

    Wednesday, June 26, 2019 11:07 PM
  • > Compiler error - what kind?

    1>C:\Users\archa\source\repos\meh\source\main.cpp(46,21): error C2760:  syntax error: unexpected token '<<', expected 'declaration'

    Basically, it doesn't like the << on the same line as the variable definition. I get this with Visual Studio 2019, 2017 and Clang/LLVM.


    This is a signature. Any samples given are not meant to have error checking or show best practices. They are meant to just illustrate a point. I may also give inefficient code or introduce some problems to discourage copy/paste coding. This is because the major point of my posts is to aid in the learning process.

    Thursday, June 27, 2019 12:41 AM