|
I get the following warning when I compile some of my source files in ANSI.
StdString.h(2091) : warning C4512: 'NotSpace<CT>' : assignment operator could not be generated
with
[
CT=char
]
StdString.h(3660) : see reference to class template instantiation 'NotSpace<CT>' being compiled
with
[
CT=char
]
To get around this warning, I modified the #else portion of the NotSpace structure with the following addition:
private:
const NotSpace & operator=(const NotSpace&);
I'm using the Jan 10 2005 (latest revision history entry) version of stdstring.h.
Does this change seem safe or is there a different way I should handle this warning?
Leo.
|
|
|
|
|
Now that's odd. I use Visual Studio 2005 as well and have used CStdString in ANSI mode with no compilation problems such as this.
However your fix is perfectly safe and should be harmless for me to add to the official version. Thanks for the message.
-Joe
|
|
|
|
|
CStdStringW sValW("??");
CStdStringA sValA = sValW; (fail when call _Wcrtomb)
|
|
|
|
|
reference from http://www.sunchangming.com/blog/?p=2022[^]
//???????????,???????????????????
//???????????????,?????????????????
//??,????win?,locale?????"chinese-simplified"???"zh_CN.GB2312"
#include <iostream>
#include <fstream>
#include <iterator>
#include <locale>
#include <string>
#include <vector>
///??????????,??’\0'
#define MAX_LENTH_PER_STRING 1024
///???locale
#define STREAM_LOCALE "chinese-simplified"
template <typename t="">
std::vector<std::basic_string><t> > readData(std::basic_istream<t>& is);
int main(int argc,char* argv[]){
std::wifstream fs("C:\\test.txt");
std::vector<std::wstring> datastrings;
try{
fs.imbue(std::locale(STREAM_LOCALE));
datastrings=readData<wchar_t>(fs);
}
catch (const std::ios::failure& error) {
std::cerr << "I/O exception: " << error.what() << std::endl;
fs.close();
return EXIT_FAILURE;
}
catch (const std::exception& error) {
std::cerr << "standard exception: " << error.what() << std::endl;
fs.close();
return EXIT_FAILURE;
}
catch (…) {
std::cerr << "unknown exception" << std::endl;
fs.close();
return EXIT_FAILURE;
}
fs.close();
std::wcout.imbue(std::locale(STREAM_LOCALE)); //?????,???????????????std::ios::failure??
std::wcout.exceptions (std::ios::failbit | std::ios::badbit);
try{
std::copy(datastrings.begin(),datastrings.end(),std::ostream_iterator<std::wstring,wchar_t>(std::wcout,L" "));
}
catch (const std::ios::failure& error) {
if(!std::wcout.eof()){
std::cerr << "I/O exception: " << error.what() << std::endl;
return EXIT_FAILURE;
}
}
catch (const std::exception& error) {
std::cerr << "standard exception: " << error.what() << std::endl;
return EXIT_FAILURE;
}
catch (…) {
std::cerr << "unknown exception" << std::endl;
return EXIT_FAILURE;
}
return 0;
}
template <typename t="">
std::vector<std::basic_string><t> > readData(std::basic_istream<t>& is){
std::vector<std::wstring> datastrings;
std::ios::iostate oldExceptions = is.exceptions
();
is.exceptions (std::ios::failbit | std::ios::badbit);
try{
while(!is.eof()){
wchar_t data[MAX_LENTH_PER_STRING];
is.getline(data, MAX_LENTH_PER_STRING, L’ ‘ );
datastrings.push_back(data);
}
}
catch (…) {
/*if exception not caused by end-of-file
*- restore old state of exception flags
*- rethrow exception
*/
if (!is.eof()) {
is.exceptions (oldExceptions); // restore
throw; // rethrow
}
}
is.exceptions (oldExceptions);
return datastrings;
}
|
|
|
|
|
so i modify the CStdString Implement Code:
from:
inline PSTR StdCodeCvt(PSTR pDstA, int nDst, PCWSTR pSrcW, int nSrc,
const std::locale& loc=std::locale())
to:
inline PSTR StdCodeCvt(PSTR pDstA, int nDst, PCWSTR pSrcW, int nSrc,
const std::locale& loc=std::locale("chinese-simplified"))
then the bug will be corrected;
|
|
|
|
|
Hi,
I am sorry to take so long to get back to you. If you are OK with changing the code that is fine. However be aware that your change makes the code a bit more "brittle", so to speak. Your code is now tied to a single locale. There is another way.
You can have your program set the global locale to "chinese-simplified". Then the code should work in the original way. When StdCodeCvt constructs a default locale object it will be the proper type
The way to set the global locale is as follows:
std::locale loc2 ("chinese-simplified");
std::locale::global(loc2);
You could do this once at the start of your program.
-Joe
|
|
|
|
|
Hello,I'm sunchangming.The author of upper code.
>std::locale loc2 ("chinese-simplified");
>std::locale::global(loc2);
yes.you can add them to the "main" function,but there are some streams that created before "main" started: std::cin,std::cout,std::cerr,std::wcin,std::wcout,std::wcerr.
so "std::locale::global(loc2)" will(if you are using libstdc++v3) or will not(if you are using vc6,vc7,vc8) change them.
|
|
|
|
|
I am use STLport 5.13 in VC6
Below at compile-time error occurred, I would like to ask how to solve theconst
StdString.h(857) : error C2059: syntax error : '<tag>::*'
SSCodeCvt& conv = SS_USE_FACET(loc, SSCodeCvt);
|
|
|
|
|
yes, I met the same problem.
|
|
|
|
|
I use your test project and modify teststring.cpp as follows:
typedef std::map<cstdstring, int,="" stdstringlessnocase=""> CMyMap;
CMyMap myMap;
myMap[_T("MYKEY")] = 7;
_ASSERTE(myMap.find(_T("mykey")) != myMap.end());
/////your code//////////
typedef stdext::hash_map<cstdstring,int> CMyHash;
CMyHash myhash;
myhash[_T("ABC")]=12;
////my code//////
and got:
error C2440: 'type cast' : cannot convert from 'const CStdString' to 'size_t' c:\vs8\vc\include\xhash 61
regards.
|
|
|
|
|
Hi,
I'm afraid I can't tell what the problem is because you need to edit your post. The declaration of your map type did not come out because the angle bracket characters are hidden. In order to make them show up, you need to use the ones from the "Formatting" bar below the editor when you are writing your post
Can you repost again showing me exactly how your map was declared, being careful to use the '<' and '>' characters from the "Formatting" section?
-Joe
|
|
|
|
|
I'm using a library from a vendor that depends on CStdString, but I'm having linking problems, so I created a new project that just includes StdString.h. Here's the entire source code:
#include "StdString.h"
int _tmain(int argc, _TCHAR* argv[])<br />
{<br />
CStdString test;<br />
return 0;<br />
}
The problem comes about during the linking state. I'm getting the follow errors:
1>st.obj : error LNK2019: unresolved external symbol "__declspec(dllimport) public: __thiscall CStdStr<wchar_t>::~CStdStr<wchar_t>(void)" (__imp_??1?$CStdStr@_W@@QAE@XZ) referenced in function _wmain<br />
1>st.obj : error LNK2019: unresolved external symbol "__declspec(dllimport) public: __thiscall CStdStr<wchar_t>::CStdStr<wchar_t>(void)" (__imp_??0?$CStdStr@_W@@QAE@XZ) referenced in function _wmain<br />
1>C:\Documents and Settings\user\My Documents\Visual Studio 2005\Projects\st\Debug\st.exe : fatal error LNK1120: 2 unresolved externals
It has some issue with the inline class members such that the linker can't find them, even though they should be in the object for st.obj. I'd appreciate any help, as it's pretty critical that we get this code running.
Thanks,
Kenny
|
|
|
|
|
First make sure you have the latest version of the code. You can get it here:
http://home.earthlink.net/~jmoleary/code/StdString.zip
Next, make sure that your application is linking in a compliant version of the Standard C++ Library. Check your project settings to be sure. As an experiment, try to use the base class and see if you also have problems. For example:
#include <string>
int _tmain(int argc, _TCHAR* argv[])
{
std::string test;
return 0;
}
Try this. Does it compile and link? If not, you have a configuration problem
-Joe
|
|
|
|
|
Joe,
Thanks for the quick reply. Trying std::string test worked fine. I downloaded the newest version, and though there were some compiler warnings, it seemed to link fine. I haven't tested it past linking yet.
Assuming it works fine, I am concerned about whether I'll be able to use it. My application is using functions from a DLL that was built against an older version of StdString.h (the one that I was originally trying). Will I see problems if I'm including the newest version in my project, but the DLL was built against an older version?
Thanks,
Kenny
|
|
|
|
|
Hmmm. It depends upon how old the DLLs.
Really CStdString is just a bunch of inline functions added on to the basic_string class. It adds no member data. So older versions of the class should work just fine with newer versions. It is irrelevant if, the current version of, say, CStdString::Format() is different from an older one because neither is acting upon any member data except through public members of basic_string itself.
There should be no binary differences because there is no "binary" whatsoever except that of the base_class basic_string.
Technically, I suppose it depends upon how old the version of CStdString is that you are linking against. In some VERY old versions (we're talking like around the year 2001 or earlier) it was not a template at all but rather a class. It had a single, static member. But those days are long gone.
Is the DLL you are using exporting functions which refer to CStdString by name? In other words, do the functions you call either take or return CStdString objects? If so, then that DLL is probably trying to export the CStdString as well. Check out the section in the StdString.h header file entitled "HOW TO EXPORT CSTDSTRING FROM A DLL". It might have some relevant comments. I wrote those comments when working with a version of Visual C++ two generations ago, however so I can't be sure how much of it still applies..
I still think you will be fine but lacking the actual code, it is difficult to be sure. Regardless
-Joe
|
|
|
|
|
Joe,
I figured things out based on the mangled names. The definition of CStdString in the DLL is CStdStringA, whereas I my code was using CStdStringW.
Thanks for the help and the code
-Kenny
|
|
|
|
|
Joe,
A message of yours on 20 Apr 06 says your latest version of the code uses:
typedef std::codecvt SSCodeCvt;
However the code I downloaded today (8/26/07) uses the following:
typedef std::codecvt<wchar_t, char, mbstate_t> SSCodeCvt;
Which is correct? I haven't tried it lately, but my original problem with Borland was on this line.
- Dave -
|
|
|
|
|
Hi Dave,
The second line is correct. Actually what you see in the second line is what I typed in the message you are referring to. But I forgot that this board interprets angle bracket characters (<,> )specially. I just typed them literally and the board promptly hid them and everything in between them. In order to make them appear you have to use those special "formatting" buttons at the bottom of the textbox when you are composing the message.
Anyway, I have gone back and edited that message to make it show up properly. Sorry for the confusion.
-Joe
|
|
|
|
|
I'm a relative beginner at C++ right now, so please bear with me if this is obvious.
Say I have a function "void RunTest(CStdString)". If I pass a MFC CString as a parameter, I get the compiler error "Cannot convert parameter 1 from 'CString' to 'CStdString'". Is there a way to pass an MFC CString into the function without having to do any explicit casts?
For example, I would just like the following code to compile and work (using the function above):
CString s;
RunTest(s);
The reason I ask is that I would like to use CStdString in some libraries, but there is already a lot of code that uses CStrings. Having to modify that code would be very tedious (and I simply don't want to mess the code up).
Also, going the other direction, I get a compiler error when I pass a CStdString in for a function expecting a CString parameter. For example, if I have a function "void RunTest2(CString)" and run the code:
CStdString stdstring;
RunTest2(stdstring);
... I get the error "Cannot convert parameter 1 from 'CStdString' to 'CString'."
It seems like this class is supposed to be able to handle these two problems directly, so I don't know if I have a compiler setting wrong or something (I'm compiling on VS .Net 2003). Is there something I'm missing here? (Again, sorry if this is an elementary question.)
|
|
|
|
|
The problem here is that you are attempting to perform two implicit conversions. C++ will only perform one for you
CString can be implicitly converted to a const TCHAR*
A const TCHAR* can be implicitly converted to a CStdString
C++ will do either of those for you automatically. However what it will NOT do is both of them.
Personally, when I am writing a function that takes a string argument which I know I am not going to change during the course of the function, I write the argument as a const TCHAR*, not as a CStdString. If I need CStdString functions, I just construct an object around the const TCHAR*.
So instead of this:
void RunTest(CStdString s)
write this
void RunTest(const TCHAR* szVal)
or this (same thing)
void RunTest(PCTSTR szVal)<br />
{<br />
<br />
CStdString s(szVal);<br />
}
Now you can call this function with just a CString object. The C++ compiler will see that the function takes a const TCHAR* and will implicitly call the CString class' conversion function for you (operator ()).
Hope this helps
-Joe
|
|
|
|
|
Hi,
Im an embedded C++ developer and my compiler is Diab and this doesnot support MFC's CString. I came across your article and felt so excited to use the portable CStdString instead of the CString. So, I just inserted your CStdString.h and tried to compile. Unfortunately, the compiler gave a whole bunch of errors saying it doesnot recognize locale.h and when I tried to include locale.h, it complains missing of another header file and when I finally included all the dependent header files (crtdefs.h,vadefs,h) of locale.h, the diab finally gave me an error saying:Only Win32 target supported.
The functions that I am interested to port are Empty() and Format() in CString of which CString is MFC dependent and my platform doesnot support it. When I tried to include your CStdString as is, the compiler gave me many errors (other than the missing header files) of which I was not able to find a solution for them. Is there a chance where you can strip off part of the code in your header file and just make the Empty() and Format() functions work in my embedded diab compiler??
Really appreciate your help. Im desperately waiting for your response.
|
|
|
|
|
OK, I don't know what is going on I have been back here many times and responded to posts but I have NEVER seen this post until right now, even though you made it in MAY. I can miss things but not that many times. Grrrrr...
Anyway I feel terrible that I never gave you a response here. At this point I imagine you have moved on but if not, please let me know. Regardless please accept my apologies for not responding to you sooner but I swear I never saw this post.
-Joe
|
|
|
|
|
I have a program. There are some CString::Format function call, and each Format's argument count are all over 17B
But in your CStdString, the safe Format can only accept at most 17 paremetes.
I don't want to undefine SS_SAFE_FORMAT, what I can do?
|
|
|
|
|
Hi,
I have to say I am surprised that any program ever called Format with more than 17 arguments. I figured that was a pretty safe number.
You could create the overloads yourself. What is the maximum number of arguments passed in? Creating overloads is just matter of copy, paste and edit.
Barring that, you have no choice but to undefine SS_SAFE_FORMAT
My main recommendation would be to not use Format at all but rather to use stringstreams. With stringstreams all the formatting is safe and there is no limit on the number of arguments. Frankly Format() and functions like it that take a variable number of arguments are not a good thing to use anyway. Streams are much better.
-Joe
|
|
|
|
|
I suggest to relpace following code
std::basic_string<char>::traits_type::copy(pDst, pSrc, nChars);
to
#if defined(_MSC_VER) && (_MSC_VER >= 1400) //if MSVC8 and later
std::basic_string<char>::traits_type::_Copy_s(pDst, nDst, pSrc, nChars);
#else
std::basic_string<char>::traits_type::copy(pDst, pSrc, nChars);
#endif
...
and
...
std::basic_string<wchar_t>::traits_type::copy(pDst, pSrc, nChars);
to
#if defined(_MSC_VER) && (_MSC_VER >= 1400) //if MSVC8 and later
std::basic_string<wchar_t>::traits_type::_Copy_s(pDst, nDst, pSrc, nChars);
#else
std::basic_string<wchar_t>::traits_type::copy(pDst, pSrc, nChars);
#endif
to avoid warning:
warning C4996: 'std::char_traits<char>::copy' was declared deprecated
c:\program files\microsoft visual studio 8\vc\include\iosfwd(446) : see declaration of 'std::char_traits<char>::copy'
Message: 'You have used a std:: construct that is not safe. See documentation on how to use the Safe Standard C++ Library
|
|
|
|
|