0

I did not write the code below, it's open source and no longer supported. I do need to make a few changes to it so I installed VC++ Express 2010 and I've managed to work out most of the problems, and the application was actually written for Windows to begin with so while it's been hair-pulling but reasonably difficult, I am making some progress.

I am stuck on one conversion and I haven't quite gotten a handle on VC++ 2010 type conversions, but here is the code giving me my last headache...

path is std::string and cFileName is WCHAR. I beleive I was successful in converting path to WCHAR, but then mEntries.push_back had a problem with it. What I beleive I need to do is convert cFileName to a string, and I have searched and tried numerous different ways to do it but I'm either getting the syntax wrong or it's not working in VC++ or I'm completely missing something else.

It would be nice to know why it does not work and why there are soooo many different "types" of strings (I write SQL Scripts, this is ridiculous) but at this point, I just need help making it work.

// Add files matching file spec to listing, returning number added. Each
// filename is prepended with its path, if one was supplied in file spec.

unsigned int DirList :: Add( const string & fspec ) {

// save path, if any
STRPOS lastslash = fspec.find_last_of( "\\/");
string path = lastslash == STRNPOS ? "" : fspec.substr( 0, lastslash + 1 );
unsigned int count = 0;
WIN32_FIND_DATA fd;
HANDLE h = FindFirstFile( LPCWSTR(fspec.c_str()), & fd );
if ( h == INVALID_HANDLE_VALUE ) {
    return count;
}

do {
    mEntries.push_back(
        new WinDirEntry(
                path + fd.cFileName,    // add path back on
                fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY
        )
    );
    count++;
} while( FindNextFile( h, & fd ) );

FindClose( h );

return count;
}

The Error message is:

error C2782: 'std::basic_string<_Elem,_Traits,_Alloc> std::operator +(std::basic_string<_Elem,_Traits,_Alloc> &&,const _Elem *)' : template parameter '_Elem' is ambiguous
1>          ...\microsoft visual studio 10.0\vc\include\string(143) : see declaration of 'std::operator +'
1>          could be 'WCHAR'
1>          or       'char'

error C2784: 'std::basic_string<_Elem,_Traits,_Alloc> std::operator +(std::basic_string<_Elem,_Traits,_Alloc> &&,std::basic_string<_Elem,_Traits,_Alloc> &&)' : could not deduce template argument for 'std::basic_string<_Elem,_Traits,_Alloc> &&' from 'WCHAR [260]'
1>   ...\microsoft visual studio 10.0\vc\include\string(109) : see declaration of 'std::operator +'

error C2676: binary '+' : 'std::string' does not define this operator or a conversion to a type acceptable to the predefined operator
Kerrek SB
  • 464,522
  • 92
  • 875
  • 1,084
Acy
  • 1
  • 1
  • 1
    A quick solution would be to use the ansi versions of `Find*`. That is explicitly using `FindFirstFileA`. Otherwise you probably want something like [WideCharToMultiByte](http://msdn.microsoft.com/en-us/library/dd374130\(v=vs.85\).aspx) – user786653 Jul 12 '11 at 17:50
  • Thanks user786653, I did try FindFirstFileA, but it had a problem with fspec so I took off the cast LPCWSTR and then it was ok with that. Unfortunately, then it had a problem with the "&" [errorC2664 cannot convert parameter 2 from WIN32_FIND_DATA * to LPWIN32_FIND_DATAA] I will look for an example for WideCharToMultiByte, I think it's a bit over my head for now... – Acy Jul 12 '11 at 18:09
  • @Acy: Continue down the line, use `WIN32_FIND_DATAA` instead of `WIN32_FIND_DATA`. – dalle Jul 12 '11 at 18:12
  • @Acy: You also need to use the Ansi version of the structure (probably called `WIN32_FIND_DATAA`). It is a mess to mix the ansi and widechar versions (and preferably your entire application should use the widechar versions as you're doing). [This](http://stackoverflow.com/questions/402283/stdwstring-vs-stdstring) SO questions seems to have more info on the conversion process. – user786653 Jul 12 '11 at 18:14
  • That worked guys thanks! It was a relatively short chain of type errors but I am compiled! Woot. – Acy Jul 12 '11 at 18:31

2 Answers2

3

Convert path from std::string to std::wstring.

std::string s("hello");
std::wstring ws;

ws.assign(s.begin(), s.end());

Create a std::wstring for cFileName, so that you have both the strings in the same type to operate.

NOTE: the assign() method works only if you are going to convert from std::string to std::wstring. The vice-versa doesn't work properly for all Unicode characters. Found this codeguru.com forum topic which talks about converting between std::string and std::wstring: How to convert string to wstring?

Reference:

MSDN: std::wstring

cplusplus.com: std::string/std::wstring

yasouser
  • 5,113
  • 2
  • 27
  • 41
0

I believe your problem is because the std::string type uses your basic char as the character type and the + operator isn't defined for std::basic_string and a wide character array. I think Visual Studio supports std::wstring which might just make this work if dropped in instead of std::string.

And there are several different kinds of string because there are a lot of different ways to encode characters. ASCII, UTF-8, etc., etc. Not all of them fit in your basic char* and you're not really insulated from that to any great degree in C++.

  • I tried wstring as well but it was an endless chain of fixing similar errors. But I agree with you and user786653, I will end up converting the whole thing to widechar types. But it's a lot of code, I didn't write any of it and I need it to compile so I can learn it. I changed a LOT of types to get to this point, it seems to go back and forth between incompatable types which must be ok in gcc. Anyway, I really hope I didn't break it too badly because it does a lot of what I need to know how to do and it needs to be able to compile in Visual Studio because I won't be the only one using it. – Acy Jul 12 '11 at 18:30