Forcing value to bool (performance warning)

H

Howard Kaikow

In the code below, ALL the lines that start with PPTfile << are getting the
following error at build time.

"//i:\C++\C++Code\FileOperations\Form1.h(127) : warning C4800:
'System::String __gc *' : forcing value to bool 'true' or 'false'
(performance warning)"

I get the following output, which is obviously wrong:

Process ID = 0x1
ref count (c) = 0x1
Thread Count = 1
parent process ID = 0x1
Priority Base = 1
Process ID = 0x1
ref count (c) = 0x1
Thread Count = 1
Process ID = 0x1
Priority Base = 1
1
1
1
1
1
-------------------------------------------------
DWORD x = 23;
LONG aa = 16;

String *buf;
ofstream PPTfile("PPT.txt", ios::blush:ut);
PPTfile << " Process ID = 0x" << x.ToString("X8") << endl;
PPTfile << " ref count (c) = 0x" << x.ToString("X4") << endl;
PPTfile << " Thread Count = " << x.ToString() << endl;
PPTfile << " parent process ID = 0x" << x.ToString("X8") << endl;
PPTfile << " Priority Base = " << aa.ToString() << endl;

buf = x.ToString("X8");
PPTfile << " Process ID = 0x" << buf << endl;
buf = x.ToString("X4");
PPTfile << " ref count (c) = 0x" << buf << endl;
buf = x.ToString();
PPTfile << " Thread Count = " << buf << endl;
buf = x.ToString("X8");
PPTfile << " Process ID = 0x" << buf << endl;
buf = aa.ToString();
PPTfile << " Priority Base = " << buf << endl;

buf = String::Concat(S" Process ID = 0x", x.ToString("X8"));
PPTfile << buf << endl;
buf = String::Concat(S" ref count (c) = 0x", x.ToString("X4"));
PPTfile << buf << endl;
buf=String::Concat(S" Thread Count = ", x.ToString());
PPTfile << buf << endl;
buf=String::Concat(S" parent process ID = 0x", x.ToString("X8"));
PPTfile << buf << endl;
buf =String::Concat(S" Priority Base = ", aa.ToString());
PPTfile << buf << endl;
PPTfile.close();
 
T

Tamas Demjen

Howard said:
In the code below, ALL the lines that start with PPTfile << are getting the
following error at build time.

"//i:\C++\C++Code\FileOperations\Form1.h(127) : warning C4800:
'System::String __gc *' : forcing value to bool 'true' or 'false'
(performance warning)"

I get the following output, which is obviously wrong:

ToString returns a .NET object handle, which native C++ can't handle,
and therefore it tries to convert it implicitly to bool. Thus the
warning. You have to use the following function (as an example) to
convert managed strings to unmanaged ones:

std::wstring ToUnmanagedString(System::String* str)
{
const wchar_t __pin* c_str = PtrToStringChars(str);
return std::wstring(c_str);
}

In addition, you shouldn't use endl, you should use "\n" instead. endl
flushes the stream, which is a serious performance penalty.

Tom
 
H

Howard Kaikow

Tamas Demjen said:
ToString returns a .NET object handle, which native C++ can't handle,
and therefore it tries to convert it implicitly to bool. Thus the
warning. You have to use the following function (as an example) to
convert managed strings to unmanaged ones:

std::wstring ToUnmanagedString(System::String* str)
{
const wchar_t __pin* c_str = PtrToStringChars(str);
return std::wstring(c_str);
}

Using the above, I got the error:

i:\C++\C++Code\FileOperations\Form1.h(101): error C2230: 'ToUnmanagedString'
: a member function of a managed class cannot return a non-managed class or
struct 'std::basic_string<_Elem,_Traits,_Ax>' unless it is an aggregate
with
[
_Elem=wchar_t,
_Traits=std::char_traits<wchar_t>,
_Ax=std::allocator<wchar_t>
]

What does that mean?
 
T

Tom Widmer

Howard said:
ToString returns a .NET object handle, which native C++ can't handle,
and therefore it tries to convert it implicitly to bool. Thus the
warning. You have to use the following function (as an example) to
convert managed strings to unmanaged ones:

std::wstring ToUnmanagedString(System::String* str)
{
const wchar_t __pin* c_str = PtrToStringChars(str);
return std::wstring(c_str);
}


Using the above, I got the error:

i:\C++\C++Code\FileOperations\Form1.h(101): error C2230: 'ToUnmanagedString'
: a member function of a managed class cannot return a non-managed class or
struct 'std::basic_string<_Elem,_Traits,_Ax>' unless it is an aggregate
with
[
_Elem=wchar_t,
_Traits=std::char_traits<wchar_t>,
_Ax=std::allocator<wchar_t>
]

What does that mean?

The supplied function should not be a member function - make it a global
or namespace scope function.

Tom
 
H

Howard Kaikow

The supplied function should not be a member function - make it a global
or namespace scope function.

Thanx.

Now, I'm getting the error

i:\C++\C++Code\FileOperations\Form1.h(162): error C2679: binary '<<' : no
operator found which takes a right-hand operand of type 'std::wstring' (or
there is no acceptable conversion)

in the following code:

DWORD x = 23;
String *buf;
ofstream PPTfile("PPT.txt", ios::blush:ut);

buf = x.ToString("X8");
PPTfile << " Process ID = 0x" << ToUnmanagedString(buf)<< "\n";

buf = String::Concat(S" Process ID = 0x", x.ToString("X8"));
PPTfile << ToUnmanagedString(buf) << "\n";

PPTfile.close();



I included the following in stdafx,h

#include <vcclr.h>

and I included the folowing at the top of the namespace, right after
using namespace System::Drawing;

std::wstring ToUnmanagedString(System::String* str)
{
const wchar_t __pin* c_str = PtrToStringChars(str);
return std::wstring(c_str);
//return std::wstring((wchar_t __pin*) PtrToStringChars(str));
}
 
H

Howard Kaikow

I stumbled upon MSFT KB artice 311259, which suggests 3 solutions, including
the one discussed in this thread.
Alas, none of the 3 solutions appear to solve the problem.

The solutions listed are:

PtrToStringChars, as discussed in this thread.
StringToHGlobalAnsi
CString
 
C

Carl Daniel [VC++ MVP]

Howard said:
Thanx.

Now, I'm getting the error

i:\C++\C++Code\FileOperations\Form1.h(162): error C2679: binary '<<'
: no operator found which takes a right-hand operand of type
'std::wstring' (or there is no acceptable conversion)

You're using a wide-character string (std::wstring) with a narrow-character
stream (std::blush:fstream). Unfortunately, that doesn't work.

What you really want is to use a wide-character stream (std::wofstream) with
a narrowing facet (assuming you want ASCII/ANSI text in your outpout file
and not Unicode). Unfortunately, VC++ does not supply a suitable facet
(although the Dinkumware Unabridged library does include one).

What you can do instead is use the .NET framework to do the narrowing
conversion for you:

<untested code>
std::string ToUnmanagedNarrowString(System::String* str)
{
HGLOBAL hg =
(HGLOBAL)System::Runtime::InteropServices::Marshal::StringToHGlobalAnsi(str);
const char* pc = static_cast<const char*>GlobalLock(hg);
std::string ret(pc,pc+str->get_Length());
GlobalFree(hg);
return ret;
}
</untested code>

Note that if Unicode output is acceptable (for example, that ofstream
actually goes to the console), simply changing your ofstream to a wofstream
should be sufficient.

-cd
 
H

Howard Kaikow

Carl Daniel said:
You're using a wide-character string (std::wstring) with a narrow-character
stream (std::blush:fstream). Unfortunately, that doesn't work.

What you really want is to use a wide-character stream (std::wofstream) with
a narrowing facet (assuming you want ASCII/ANSI text in your outpout file
and not Unicode). Unfortunately, VC++ does not supply a suitable facet
(although the Dinkumware Unabridged library does include one).

What you can do instead is use the .NET framework to do the narrowing
conversion for you:

<untested code>
std::string ToUnmanagedNarrowString(System::String* str)
{
HGLOBAL hg =
(HGLOBAL)System::Runtime::InteropServices::Marshal::StringToHGlobalAnsi(str)
;
const char* pc = static_cast<const char*>GlobalLock(hg);
std::string ret(pc,pc+str->get_Length());
GlobalFree(hg);
return ret;
}
</untested code>

Note that if Unicode output is acceptable (for example, that ofstream
actually goes to the console), simply changing your ofstream to a wofstream
should be sufficient.

I an writing to a file.

I already display the info in a listbox, I'm just trying to get the stuff
from the listbox into a file, so I can print the file.
Perhaps there's a better way to do that?
 
C

Carl Daniel [VC++ MVP]

Carl said:
<untested code>
std::string ToUnmanagedNarrowString(System::String* str)
{
HGLOBAL hg =
(HGLOBAL)System::Runtime::InteropServices::Marshal::StringToHGlobalAnsi(str);
const char* pc = static_cast<const char*>GlobalLock(hg);

const char* pc = static_cast said:
std::string ret(pc,pc+str->get_Length());
GlobalFree(hg);
return ret;
}
</untested code>

-cd
 
C

Carl Daniel [VC++ MVP]

Howard said:
"Carl Daniel [VC++ MVP]"
Note that if Unicode output is acceptable (for example, that ofstream
actually goes to the console), simply changing your ofstream to a wofstream
should be sufficient.

I an writing to a file.

I already display the info in a listbox, I'm just trying to get the
stuff from the listbox into a file, so I can print the file.
Perhaps there's a better way to do that?

No, not really. If you're using .NET for your UI (and hence Unicode) and
youi want to write out a narrow-character file, then you have to explicitly
do the narrowing conversion somewhere.

-cd
 
H

Howard Kaikow

Carl Daniel said:
No, not really. If you're using .NET for your UI (and hence Unicode) and
youi want to write out a narrow-character file, then you have to explicitly
do the narrowing conversion somewhere.

I have no problem using the same expressions when adding to a LIstBox
control.
So, I expect that I should byte the bullet and use the System::IO
namespace.
 
H

Howard Kaikow

Thanx to those who helped in this thread.

I yelled Uncle!
I've used StreamWriter from the System::IO namespace to eliminate the
problems.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top