I've got a template class derived from std::basic_stringstream<typename TString::value_type...>, as you can see. The problem happens while trying to convert them. It's probably an obvious problem, though I cannot seem to figure out the solution.
As example in main, I have a simple std::wstring and initialize it with L"123".
After the std::wstring has been constructed, the operator of the custom basic_stringstream class is called (depending on std::wstring or std::string).
Inspecting the WCStringStream object for debugging purposes, shows that it contains - instead of the string L"123", the address of the first element of the entered string. The functions to_bytes and from_bytes do return the correct converted string, so the only problem left is the operator being called in both operator-functions:
*this << std::wstring_convert<...>().xx_bytes(s);
Example:
Template class is std::wstring.
Input is a std::string.
&operator<<(const std::string &s) is being called.
String is converted.
&operator<<(const std::wstring &s) is being called.
String-type matches with template type.
Operator of base-class (basic_stringstream) is called. (Or std::operator...)
Result:
Inspecting: {_Stringbuffer={_Seekhigh=0x007f6808 L"003BF76C췍췍췍췍췍췍췍췍췍...}...}
WCStringStream<std::wstring>::str() -> "003BF76C"
Expected result:
"123"
What's going wrong here ?
#define WIN32_LEAN_AND_MEAN
#define NOMINMAX
#include <Windows.h>
#include <iostream>
#include <sstream>
#include <codecvt>
template<class TString>
class WCStringStream : public std::basic_stringstream<typename TString::value_type,
std::char_traits<typename TString::value_type>,
std::allocator<typename TString::value_type> >
{
typedef typename TString::value_type CharTraits;
typedef std::basic_stringstream<CharTraits, std::char_traits<CharTraits>, std::allocator<CharTraits> > MyStream;
//more typedefs...
public:
//Constructor...
inline WCStringStream(void) { }
inline WCStringStream(const TString &s) : MyStream(s) { }
//and more...
//operator>> overloads...
//defines for VS2010/2015 (C++11) included
inline WCStringStream &operator<<(const std::wstring &s)
{
if (typeid(TString) == typeid(s))
MyStream::operator<<(s.c_str());
else
*this << std::wstring_convert<std::codecvt_utf8<wchar_t>, wchar_t>().to_bytes(s);
return *this;
}
inline WCStringStream &operator<<(const std::string &s)
{
if (typeid(TString) == typeid(s))
MyStream::operator<<(s.c_str());
else
*this << std::wstring_convert<std::codecvt_utf8<wchar_t>, wchar_t>().from_bytes(s);
return *this;
}
};
//Example main
int main(int argc, char *argv[])
{
typedef std::wstring fstring;
WCStringStream<std::wstring> ws;
WCStringStream<std::string> ss;
ws << fstring(L"123");
int a = 0;
ws >> a;
std::cout << a << std::endl;
ss << fstring(L"123");
int b = 0;
ss >> b;
std::cout << b << std::endl;
return 0;
}
I'm compiling currently in VS2015 but I'd need it to run on VS2010 too.
stringstreamdid this for you alreadystd::stringstreamandstd::wstringstream, I'd like to "combine" these with additional functions not being displayed here.typeid(..) == typeid(..)supposed to be a compile-time check? Because it currently isn't.... Wouldn'tstd::is_same<TString, std::string>::valuebe more appropriate, or template specialization?std::string convert(std::wstring const&); std::wstring convert(std::string const&);, then define the two operators e.g. via a type functiontemplate<class T> using other_string_type = typename std::conditional<std::is_same<T, std::string>::value, std::wstring, std::string>::type;thenWCStringStream& operator<< (TString const&); WCStringStream& operator<< (other_string_type<TString> const&);