Question

I have built up a string using wstringstream and need to assign it to a member of a struct of type LPWSTR. I try to use my_stringstream.str().c_str() but get the following compile time error:

cannot convert from 'const wchar_t *' to 'LPWSTR'

How can I do this? I have tried many different combinations of casts with either more compile time errors or random jargon when I try and display the string in a GUI.

Was it helpful?

Solution

Your function expects a pointer to modifiable data, i.e. wchar_t*, but the standard string class only exposes a pointer to constant. Assuming that your function may actually write to the memory, we need to provide it with a valid pointer.

An easy way to obtain a modifiable buffer is, as always, a vector:

std::vector<wchar_t> buf(mystring.begin(), mystring.end());
buf.push_back(0);                 // because your consumer expects null-termination

crazy_function(buf.data());
crazy_function(&buf[0]);          // old-style

// need a string again?
std::wstring newstr(buf.data());  // or &buf[0]

OTHER TIPS

LPWSTR is typedefd as wchar_t*. You're trying to convert a const wchar_t* to a wchar_t*. You can't do that implicitly.

You can get around this by using const_cast, but only if you are certain the function won't modify the memory:

wstring str = my_stringstream.str();
LPWSTR str = const_cast<LPWSTR>(str.c_str());

Note that you do not want to do const_cast<LPWSTR>(my_stringstream.str().c_str()) (unless you are passing that to a function) because that will create a temporary string object, get it's pointer, convert it to a LPWSTR and then the temporary string you get from str() will be destroyed at the end of that line, leaving your LPWSTR pointing to a deallocated block of memory.

If the function you are passing the LPWSTR to is modifying the string, see Kerrek's answer.

If you are absolutely sure that the content of the string will not be modified, you can cast the const away via a static_cast; a situation where this can be acceptable for example is if you are using some struct to provide data to a function, but the same struct is also used for retrieving it, so that member is LPWSTR instead of just an LPCWSTR.

If, on the contrary, the function to which you'll pass the struct needs to modify the string, you have two alternatives.

The safest one is to allocate a separate copy of the string as a raw dynamic array of WCHAR and copy there the content of the wstring. You will probably want to wrap the result of the new with a smart pointer, unless you're transferring the ownership of the string (and in that case you'll probably have to use some special allocation function).

You can also pass a pointer to the internal buffer of the string using &YourString[0], but (1) I'm not sure it's guaranteed to work by the standard, and (2) it works fine only if the function won't change the length of your string adding a L'\0' before the end of it; in this case you should also re-adjust the actual length of the string.

Both in the last and in the first case you must be sure that the function you're passing the struct to do not expect the pointed buffer to live longer than the scope of your wstring (careful: mystream.str() is a temporary that dies on the very line you use it, you have to assign it to a new variable to give it a broader scope).

  wstringstream b;
    ..
    wchar_t z[100];
    b.read(z,100);

where string length known to be less then 101. it works without unsetf(std::ios_base::skipws) and all this. And without ZeroMemory on wchar_t array.

The reason for this is rather simple: LPWSTR expands to wchar_t *. As the pointer to the stream contents is a const, it's not possible to cast this const away, unless using const_cast<LPWSTR>(my_stringstream.str().c_str()). However I'd advice against this (as you might simply screw this up and/or modify something different that way. Only do it if you're sure it won't be modified or the modification won't matter.

The easiest (and most secure solution) is to create your own copy of the string provided by the wstringstream in a buffer and refer to this one in the struct. Just don't forget to free the memory later on.

std::wstring temp(my_stringstream.str());
lpwstrVar = &temp[0];
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top