Reputation: 156
I have a little C++ question. I keep getting the same error and i don't know what to do about it.
vector<wstring> files;
if (ListFiles(L"C:", L"*.txt", files)) {
for (vector<wstring>::iterator it = files.begin(); it != files.end(); ++it) {
DoSomethingWithIt(it->c_str(), false);
}
}
Is the code.
And this is the error i get:
argument of type "const wchar_t *" is incompatible with parameter of type "LPTSTR"
The error is for the it->c_str() part in the code. Does anyone knows how to fix this and make what i want work?
Upvotes: 0
Views: 589
Reputation: 3765
I assume DoSomethingWithIt
has signature void DoSomethingWithIt(LPTSTR, BOOL)
. In this case, you can do any of the following:
Modify DoSomethingWithIt()
to accept LPCTSTR
(which is typedef for const char*
or const wchar_t*
) instead of LPTSTR
. This may not be feasible if DoSomethingWithIt()
is out of your control, or actually needs to modify the buffer you passed into it.
Modify your calling site to pass wchar_t*
instead of const wchar_t*
by forcefully casting the const
modifier away with C-style cast:
DoSomethingWithIt((LPWSTR)it->c_str(), false);
or with const_cast
operator of C++, specifically designed for this usage:
DoSomethingWithIt(const_cast<wchar_t*>(it->c_str()), false);
This opens a whole can of worms which may or may not crawl under you skin and eat your internal organs without you noticing it until it's too late, so I would advise against it. One day the way you obtain files
may change and your it
will become a const iterator, and if DoSomethingWithIt()
actually may modify the buffer you passed into it, and it will end in undefined behaviour.
Modify your calling site to pass wchar_t*
instead of const wchar_t*
by somehow asking the string for the wchar_t*
pointer to its first character. One way would be this:
std::wstring& str = *it;
DoSomethingWithIt(&str[0], false);
or if you prefer more condensed and cryptic style, like this:
DoSomethingWithIt(&((*it)[0]), false);
Another way to do the same is to use &*str->begin()
instead of &str[0]
or &*(it->begin())
instead of &((*it)[0])
. However, I personally would consider this last way to be too cryptic for my taste.
This may lead to changes of the elements of files
vector, if DoSomethingWithIt()
may actually modify the buffer you passed into it which may or may not be acceptable to you. However, if later you will change your code in such a way that it
becomes a const iterator, the compiler will actually detect it and will complain with exactly the same error it complains now, which would allow you to re-think the code and perhaps use the next snippet.
Modify your calling site to pass wchar_t*
instead of const wchar_t*
by copying the contents of *it
string into an array of wchar_t
s (of sufficient length), and the pass the pointer to its first element to DoSomethingWithIt
:
std::wstring temp = *it;
DoSomethingWithIt(&temp[0], false);
or
std::vector<wchar_t> temp(it->begin(), it->end());
temp.push_back(0); // Don't forget the trailing NUL char
DoSomethingWithIt(&temp[0], false);
This way, the contents files
are guaranteed to not change, but it may or may not lead to a slight performance penalty compared to previous solutions. I also have to add that the last way (with the temporary vector) is the most reliable of all, because technically, in C++03, std::wstring
is not obliged to store its data in a contiguous block. However, since such implementations are almost unheard of and C++11 mandates that std::wstring
has store its data in a contigous block, this is not a large concern.
If you want to use this solution, but also keep changes that DoSomethingWithIt()
made with the buffer in your files
(provided it didn't overflow the buffer and kept it null-terminated!), you'll have to add something like this after the DoSomethingWithIt()
call:
it->assign(&temp[0], &temp[0] + wcslen(&temp[0]));
.
Upvotes: 1