|
I've already talked to "inner" via email but just to post officially here, the warnings he listed are actually ALL caused by the VC6 implementation of the Standard C++ Library. It was a poor implementation and Dinkumware got rid of all these warnings in their next release.
In the meantime, those of you who have VC6, you'll need to #pragma the warnings away. Sorry. I didn't put the #pragmas in the StdString.h header because a) the warnings are harmless and b)I prefer to leave the choice up to the person using the code since their caused by code that's completely out of my control (Dinkumware's VC6 C++ Library).
I generally place the #pragmas in my precompiled header file.
-Joe
|
|
|
|
|
In VS 7.0 only one level 4 warning is displayed when compiling this class, with 'Detect 64 bit Portability issues' turned off. I've modified the class below to remove it:
template<typename ct="">
struct NotSpace : public std::unary_function<ct, bool="">
{
// DINKUMWARE BUG:
// Note -- using std::isspace in a COM DLL gives us access violations
// because it causes the dynamic addition of a function to be called
// when the library shuts down. Unfortunately the list is maintained
// in DLL memory but the function is in static memory. So the COM DLL
// goes away along with the function that was supposed to be called,
// and then later when the DLL CRT shuts down it unloads the list and
// tries to call the long-gone function.
// This is DinkumWare's implementation problem. If you encounter this
// problem, you may replace the calls here with good old isspace() and
// iswspace() from the CRT unless they specify SS_ANSI
const std::locale loc;
NotSpace(const std::locale& locArg=std::locale()) : loc(locArg) {}
bool operator() (CT t) const { return !std::isspace(t, loc); }
private:
// Private copy assignment resolve the C4512 warning.
const NotSpace &operator=(const NotSpace&); // Added line
};
|
|
|
|
|
It surely should be interesting and useful a CString-clone not using Microsoft C++ ...
So I test to compile Borland Builder C++, and it gives :
==========================================================
Borland C++ 5.6 for Win32 Copyright (c) 1993, 2002 Borland
.\TestString.cpp:
Error E2451 .\StdString.h 442: Undefined symbol 'mbstate_t'
Error E2451 .\StdString.h 463: Undefined symbol 'result' in function StdCodeCvt(wchar_t *,const char *,int,const _STL::locale &)
Error E2379 .\StdString.h 463: Statement missing ; in function StdCodeCvt(wchar_t *,const char *,int,const _STL::locale &)
Error E2451 .\StdString.h 465: Undefined symbol 'state_type' in function StdCodeCvt(wchar_t *,const char *,int,const _STL::locale &)
Error E2379 .\StdString.h 465: Statement missing ; in function StdCodeCvt(wchar_t *,const char *,int,const _STL::locale &)
Error E2451 .\StdString.h 466: Undefined symbol 'res' in function StdCodeCvt(wchar_t *,const char *,int,const _STL::locale &)
Error E2316 .\StdString.h 466: 'in' is not a member of 'SSCodeCvt' in function StdCodeCvt(wchar_t *,const char *,int,const _STL::locale &)
Error E2451 .\StdString.h 466: Undefined symbol 'st' in function StdCodeCvt(wchar_t *,const char *,int,const _STL::locale &)
Error E2451 .\StdString.h 469: Undefined symbol 'ok' in function StdCodeCvt(wchar_t *,const char *,int,const _STL::locale &)
Error E2451 .\StdString.h 486: Undefined symbol 'result' in function StdCodeCvt(char *,const wchar_t *,int,const _STL::locale &)
Error E2379 .\StdString.h 486: Statement missing ; in function StdCodeCvt(char *,const wchar_t *,int,const _STL::locale &)
Error E2451 .\StdString.h 488: Undefined symbol 'state_type' in function StdCodeCvt(char *,const wchar_t *,int,const _STL::locale &)
Error E2379 .\StdString.h 488: Statement missing ; in function StdCodeCvt(char *,const wchar_t *,int,const _STL::locale &)
Error E2451 .\StdString.h 489: Undefined symbol 'res' in function StdCodeCvt(char *,const wchar_t *,int,const _STL::locale &)
Error E2316 .\StdString.h 489: 'out' is not a member of 'SSCodeCvt' in function StdCodeCvt(char *,const wchar_t *,int,const _STL::locale &)
Error E2451 .\StdString.h 489: Undefined symbol 'st' in function StdCodeCvt(char *,const wchar_t *,int,const _STL::locale &)
Error E2451 .\StdString.h 492: Undefined symbol 'ok' in function StdCodeCvt(char *,const wchar_t *,int,const _STL::locale &)
Error E2034 .\StdString.h 1111: Cannot convert 'unsigned int' to 'const wchar_t *' in function ssvsprintf(wchar_t *,unsigned int,const wchar_t *,void *)
Error E2342 .\StdString.h 1111: Type mismatch in parameter '__format' (wanted 'const wchar_t *', got 'unsigned int') in function ssvsprintf(wchar_t *,unsigned int,const wchar_t *,void *)
Error E2034 .\StdString.h 1111: Cannot convert 'const wchar_t *' to 'void *' in function ssvsprintf(wchar_t *,unsigned int,const wchar_t *,void *)
Error E2342 .\StdString.h 1111: Type mismatch in parameter '__arglist' (wanted 'void *', got 'const wchar_t *') in function ssvsprintf(wchar_t *,unsigned int,const wchar_t *,void *)
Error E2227 .\StdString.h 1111: Extra parameter in call to vswprintf(wchar_t *,const wchar_t *,void *) in function ssvsprintf(wchar_t *,unsigned int,const wchar_t *,void *)
Warning W8058 C:\BORLAND\include\stlport/locale 150: Cannot create pre-compiled header: initialized data in header
Error E2268 .\TestString.cpp 15: Call to undefined function '_bstr_t' in function main(int,char * *)
Error E2268 .\TestString.cpp 26: Call to undefined function '_ASSERTE' in function main(int,char * *)
Error E2451 .\TestString.cpp 56: Undefined symbol 'SetResourceHandle' in function main(int,char * *)
Error E2228 .\TestString.cpp 56: Too many error or warning messages in function main(int,char * *)
*** 26 errors in Compile ***
==========================================================
I think there are more errors ...
How It can be handled ?
Maybe solving for GCC (g++) it could run on BBuilder.
Thanks in advance
Miguel PS
|
|
|
|
|
You may want to try Str Library at http://www.utilitycode.com/str - it does support your scenario
It does work with Borland C++ Builder. By the way, porting code written for Visual C++ to BCB is not trivial - the compilers are quite different
|
|
|
|
|
First lets make sure you have the very latest version. You may always grab that here
http://home.earthlink.net/~jmoleary/code/StdString.zip
Please grab that and try again. I know that my code has successfully built on Borland C++ Builder in the past.
-Joe
p.s. I apologize for taking so long to respond to this. I must have missed the email notification. I only became aware of it after the first response to your question.
|
|
|
|
|
still the same problem (with the latest version too). I think you missed some library however i dont know which. Please help.
When you do things right people wont be sure you have done anything
|
|
|
|
|
Not sure how to proceed with this. Taking a look at the very first error in the message that 'miguelps' provided, I'm confused. It complains about 'mbstate_t' not being a known type. Well 'mbstate_t" is a pretty basic type of the Standard C++ Library. I know I've included the required files. Perhaps there is a namespace issue. Something is fundamentally wrong here but, lacking Borland C++, I don't know how to determine it. My best guess is that the version of the Standard C++ Library that comes with your compiler is not up-to-date. Can you get an update from Borland?
Barring that, can you try the latest GCC?
-Joe
|
|
|
|
|
It surely should be interesting and useful a CString-clone not using Microsoft C++ ...
So I test to compile with gcc (g++, gpp), and I get the following:
==========================================================
Compiler: Default compiler
Executing g++.exe...
g++.exe ".\TestString.cpp" -o ".\TestString.exe" -fexpensive-optimizations -O1 -I"C:\DEV-CPP\include\c++" -I"C:\DEV-CPP\include\c++\mingw32" -I"C:\Dev-Cpp\include\c++\backward" -I"C:\Dev-Cpp\include" -L"C:\DEV-CPP\lib"
In file included from ./TestString.cpp:5:
./StdString.h: In function `int ssvsprintf(WCHAR*, unsigned int, const
WCHAR*, char*)':
./StdString.h:1111: invalid conversion from `size_t' to `const wchar_t*'
./StdString.h:1111: cannot convert `const WCHAR*' to `char*' for argument
`3' to `int vswprintf(wchar_t*, const wchar_t*, char*)'
./StdString.h: At global scope:
./StdString.h:1693: warning: friend declaration `CStdStr<ct>
operator+(const CStdStr<ct>&, const CStdStr<ct>&)' declares a non-template
function
./StdString.h:1693: warning: (if this is not what you intended, make sure
the function template has already been declared and add <> after the
function name here) -Wno-non-template-friend disables this warning
./StdString.h:1694: warning: friend declaration `CStdStr<ct>
operator+(const CStdStr<ct>&, CT)' declares a non-template function
./StdString.h:1695: warning: friend declaration `CStdStr<ct>
operator+(const CStdStr<ct>&, const CHAR*)' declares a non-template function
./StdString.h:1696: warning: friend declaration `CStdStr<ct>
operator+(const CStdStr<ct>&, const WCHAR*)' declares a non-template
function
./StdString.h:1697: warning: friend declaration `CStdStr<ct>
operator+(const CHAR*, const CStdStr<ct>&)' declares a non-template function
./StdString.h:1698: warning: friend declaration `CStdStr<ct>
operator+(const WCHAR*, const CStdStr<ct>&)' declares a non-template
function
In file included from ./TestString.cpp:5:
./StdString.h:3015:31: warning: no newline at end of file
./TestString.cpp: In function `int main(int, char**)':
./TestString.cpp:15: `_bstr_t' undeclared (first use this function)
./TestString.cpp:15: (Each undeclared identifier is reported only once for
each function it appears in.)
./TestString.cpp:26: `_ASSERTE' undeclared (first use this function)
./TestString.cpp:56: no method `CStdStr<char>::SetResourceHandle'
./TestString.cpp:57: `IDS_STRING1' undeclared (first use this function)
./TestString.cpp:60: `IDS_STRING2' undeclared (first use this function)
./StdString.h: In member function `bool CStdStr<ct>::Equals(const CT*,
bool) const [with CT = char]':
./TestString.cpp:27: instantiated from here
./StdString.h:1785: no matching function for call to `ssicmp(
CStdStr<char>, const char*&)'
Execution terminated
==========================================================
How It can be handled ?
Thanks in advance
Miguel PS
|
|
|
|
|
As in the above question, it would appear you have an out-of-date version of the code. Please try to grab the latest version from this link:
http://home.earthlink.net/~jmoleary/code/StdString.zip
This should make things much better. Please let me know if you have any other problems. Clearly I have been lax in following this board but I will be more vigilant in the future.
-Joe
|
|
|
|
|
Hello,
I experienced a small problem with compiling this under linux with g++.
gcc version 3.2.3 20030502 (Red Hat Linux 3.2.3-42)
Compiling:
==================================================
g++ -g -fno-rtti -O3 -c main.cpp -o main.o
In file included from main.cpp:19:
StdString.h: In function `int ssvsprintf(wchar_t*, unsigned int, const
wchar_t*, char*)':
StdString.h:1627: invalid conversion from `const wchar_t*' to `unsigned int'
StdString.h:1627: cannot convert `char*' to `const wchar_t*' for argument `3'
to `int vswprintf(wchar_t*, unsigned int, const wchar_t*, char*)'
main.cpp:48:1: warning: no newline at end of file
make: *** [main.o] Error 1
StdString.h:
-----------------------------------------------------------------------------
1623: #elif defined(__sgi)
1624:
1625: nCount;
1626: return vsprintf( (char *)pW, (char *)pFmtW, vl);
1627:
1628:#else
1629:
1630: nCount;
1631: return vswprintf(pW, pFmtW, vl);
1632:
1633: #endif
-------------
>> man vsprintf
vswprintf - formatted wide character output conversion
int vswprintf(wchar_t *wcs, size_t maxlen,
const wchar_t *format, va_list args);
Solution:
I commented line number 1615 and everything compiled and works fine, so it would be like this:
StdString.h:
#if !defined(_MSC_VER) \
&& !defined (__BORLANDC__) \
1615: //&& !defined(__GNUC__) \
&& !defined(__sgi)
return vswprintf(pW, nCount, pFmtW, vl);
// suddenly with the current SGI 7.3 compiler there is no such function as
// vswprintf and the substitute needs explicit casts to compile
#elif defined(__sgi)
-----------------------------------------------------------------------------------------
It is just a small issue, and everything else works perfectly fine.
And I would like to thank YOU, and all other people, which helped
to create that wonderful class.
I did manage to compile my class, which I wrote under VS7 with CString, using CStdString under Linux without any changes (well, concerning the using of the CString).
THANK YOU.
|
|
|
|
|
Hi,
I'm glad you've had some success with my code. The vsprintf() thing causes a lot of problems and I still have no foolproof solution for all platforms.
There is a somewhat more recent (than CodeProject's) version of the code available at the usual place:
http://home.earthlink.net/~jmoleary/code/StdString.zip.
It includes a minor performance optimization for Replace() and alerts you to possible problems that might occur if you don't have a length-checked formatting function available on your platform
-Joe
-Joe
|
|
|
|
|
I just have a question that if I can use CStdString type of variable where char* is needed. I am afraid it is going to cause crashes. Any help will be greatly appreciated.
|
|
|
|
|
Do you mean where char* is required or const char * ?
For const char* it is no problem. The class has an implicit cast operator to that or you can call c_str() to retrieve the const char* . For example:
<br />
int main(void)<br />
{<br />
<br />
FILE* file = fopen("myfile.txt", "w");<br />
CStdString sName = "Joe";<br />
<br />
<br />
fprintf(file, sName);<br />
<br />
<br />
fprintf(file, sName.c_str());<br />
<br />
return 0;<br />
}<br />
<br />
<br />
For char* you need to be a little more careful since you are effectively giving direct access to the internal buffer of the string class out to another function. To access a CStdtring as a char* you do the same thing you would do with MFC's CString: Call the GetBuffer() function. When access to that internal buffer is no longer needed, call the ReleaseBuffer() function
It is up to you to make sure that you have allocated enough space in the buffer for whatever code you pass it of to. But that's the same problem you would have if you simply allocated a flat char[] array on the stack or got a char* from heap memory. In other words, there is no greater danger using CStrString's internal buffer than there would be using a simple char buffer.
Here's a really dopey example to show how it works.
<br />
<br />
<br />
void GetNameOfCity(char* buf, int nMaxChars)<br />
{<br />
strncpy(buf, "Boston", nMaxChars)<br />
}<br />
<br />
<br />
int main(void)<br />
{<br />
CStdString str;<br />
str.FillStringBuffer(str.GetBuffer(20), 20);<br />
str.ReleaseBuffer();<br />
return 0;<br />
}<br />
<br />
-Joe
|
|
|
|
|
Just a heads up for you Joe, in VS 7.1, when you turn on the compiler option 'Detect 64 bit Portability issues' (option is under Project > Properties > C/C++ > General) StdString.h generates quite a number of warnings. Looks like quite a few static_cast<>'s are needed
|
|
|
|
|
Joe,
many thanks for this class, I've been using it for years with great success.
Right now I'm having difficulty with the SS_NO_REFCOUNT directive, is as much as turning it on prevents compilation. I was wondering if I'd missed something or if indeed there was a problem. This is the compiler error...
c:\dev\fsiv30\platform\microsoft\fsiv30lib\fsilibtest\stdstring.h(2156) : error C2352: 'std::basic_string<char,struct std::char_traits<char="">,class std::allocator<char> >::assign' : illegal call of non-static member function
c:\program files\microsoft visual studio\vc98\include\xstring(132) : see declaration of 'assign'
c:\dev\fsiv30\platform\microsoft\fsiv30lib\fsilibtest\stdstring.h(2144) : while compiling class-template member function 'class CStdStr<char> &__thiscall CStdStr<char>::assign(const char *,unsigned int)'
It occurs on line 2156 of stdstring.h...
Q172398(*this);
>>>>> MYBASE::assign(pC, nChars);
return *this;
If you can offer any feedback I'd appreciate it. I'd rather not go down the route of statically linking the CRT. Right now I'm developing a multithreaded application for Win32 but in the very near future I will need
to develop a similar app for Linux too.
Many thanks
matthew sell
|
|
|
|
|
Hi Matthew,
Sorry to take so long to get back to you.
I'll have to go build my test app tonight with SS_NO_REFCOUNT turned on. I admit it's been awhile since I've done that.
But please be aware, you only need the SS_NO_REFCOUNT setting if you are building with Visual C++ 6.0 with the original version of the Standard C++ Library that came with it. VC7 removes refcounting anyway so it is not needed.
I'll take a look at it tonight or tomorrow night and get back to you
-Joe
-Joe
|
|
|
|
|
The sample code crashes when I add the following:
<br />
CStdString s, t = "test";<br />
s.Format("%s", t);<br />
It is a known problem of va_list / vsprintf implementation of Format functions in custom string classes. If s.Format("%s", (LPCTSTR)t); is used, everything's fine - but I find it annoying to cast a string to LPCTSTR whenever I need to pass it to Format.
Does anyone know a pretty solution to this, except for the full-blown custom Format that is used by MFC's CString?
Regards,
BB
|
|
|
|
|
Well, there IS a pretty solution to it, but it only works for Format(). It does NOT work for sprintf, fprintf, or any other non-CStdString-member function.
Download the latest version here
http://home.earthlink.net/~jmoleary/code/StdString.zip
In it, you will find a version of Format that is specially written to avoid this problem. Basically what I did was overload a member template function to take anywhere from 1 to 17 arguments. Each overload will safely convert the CStdString into an LPCTSTR for you. So as long as you're not passing more than 17 objects to this function, you can avoid this crash.
So your sample code should work just fine.
CStdString s, t = "test";<br />
s.Format("%s", t);
But the following code would still crash
char buf[100];<br />
CStdStringA t = "test";<br />
sprintf(buf, "%s", t);
Is this a hack on my part? Definitely. But you know what? The fact that you are able to pass an MFC CString as a variable argument to a variadic function without casting it is hack as well. Even Microsoft recommends you explicitly cast a CString when passing it to a variadic function. They just let you get away with not doing it.
If it makes any difference, you don't have to cast to LPCTSTR. You can do the slightly less verbose call to c_str() member function. Like this
CStdString s, t = "test";<br />
s.Format("%s", t.c_str());
Still annoying. But we're all supposed to be using streams now anyway, right?
CStdString s, t = "test";<br />
std::stringstream oss<br />
oss << t;<br />
s = oss.str();
-Joe
|
|
|
|
|
Thank you for the solution hint, Joe! I will check out whether it can be simplified by using even more template tricks.
Regards,
BB
|
|
|
|
|
Thanks for this it will save me hours!
However when I add this to my MFC project I get an error in the second archive operator.
The error raised for line 3886 and is:
error C2440: 'initializing' : cannot convert from 'const CStdStringW' to 'ATL::CStringT<BaseType,StringTraits>'
I don't intend to use these operators so I just got rid of them. I just thought I would mention it, to see if there is a solution. I am using VS.Net 7.1.
After I git rid of these lines I was left with the type cast warnings that other people have mentioned. I think I have the latest version, as I have just downloaded it.
What is the best means of getting rid of these warnings.
Thanks again
AndyC
|
|
|
|
|
Hi Andy,
That's actually a minor error that someone pointed out to me a few months ago but that I still haven't fixed. It occurs when the preprocessor macro
_ATL_CSTRING_EXPLICIT_CONSTRUCTORS
is #defined.
The fix is to change this line in the CArchive operator <<:
CString strTemp = strW;
Into this line
CStdString strTemp(strW);
I keep meaning to post the update but I always forget about it. Sorry. If you change your local copy you should be able to build.
But that fix aside, there should not be any compiler warnings. If you are getting them, could you email them to me? I thought I had eliminated them all. It would appear I missed some.
-Joe
|
|
|
|
|
I am seeing this same error with VS.Net 7.1. I have the version dated 2/16/05.
"cannot convert from 'const CStdStringW' to 'ATL::CStringT<basetype,stringtraits>'"
Does anyone have an answer to this issue yet?
|
|
|
|
|
Hi Alan,
Did you try making the one-line fix I suggested in my other response to this thread?
Basically you change this line:
CString strTemp = strW;
into this line
CString strTemp(strW);
I admit I should have changed this myself already. I am unable to access my website via FTP right now so I can't do it at this moment.
-Joe
|
|
|
|
|
That worked, thanks.
Your first post showed:
CStdString strTemp(strW);
changing it to
CString strTemp(strW);
That fixes the problem.
Thanks.
|
|
|
|
|
I recently received an email with a question about CStdString from someone named "Marcus Gesing". Unfortunately the reply address did not work (The gmx.net servers did not have a usernamed "mgesing") so I am unable to reach him.
Marcus, if you see this, please respond to this post and I will attempt to answer your question. The solution should be quite simple, I think
std::locale::global(std::locale(""));
-Joe
|
|
|
|
|