visual c++ operator += is ambiguous - visual-studio-2010

CString szMsg;
//Other non related code
//stOrderInfo.bstrOrderNum is defined as a _bstr_t
szMsg += ", Order: " + stOrderInfo.bstrOrderNum;
I'm converting the above from VS 6.0 to VS2k10 and I'm getting the following error (compiles in VS 6.0):
error C2593: 'operator +=' is ambiguous
What exactly does this mean and how can I fix it?

Because you've hard-coded ", Order: " the compiler is having a hard time to decide which type it should be.
The obvious type should be CString, but it might try to make it to some other string type, and add the number to it.
So it probably can't decide if it's a CString or another string type. So it can't decide what type you're adding to szMsg.
You could just use a type cast:
szMsg += (CString)(", Order: ") + (CString)((char *)(stOrderInfo.bstrOrderNum));
Cast between string types:
How to: Convert Between Various String Types

This means that compiler cannot choose which + operation to use for BSTR + char concatenations. You have a mismatch of three types: CString, _bstr_t, and char.
Try to unify all three operands to a single type, e.g. to CString

The implementation of CString::operator+= is known to have changed in Visual Studio 2010. For example in previous versions it handled embedded null characters OK, just like operator+ keeps doing, but the new version doesn't. So it might be related to this.
EDIT
Link to discussion on this topic:
http://social.msdn.microsoft.com/Forums/en-US/vcmfcatl/thread/c5d7f383-da80-4776-b9b8-a6065839bd87

Better use CString::AppendFormat. But ensure you pass correct format-specifier.

Related

How to get gcc to compile 16-bit unicode strings

So I'm trying to compile this project : https://github.com/dmitrystu/libusb_stm32 with Segger Embedded studio which uses gcc. The process is choking on this error :
pasting formed 'u"Open source USB stack for STM32"', an invalid preprocessing token
which is caused by this line :
static const struct usb_string_descriptor manuf_desc_en = USB_STRING_DESC("Open source USB stack for STM32");
So USB_STRING_DESC is a macro :
#define USB_STRING_DESC(s) {.bLength = sizeof(CAT(u,s)),.bDescriptorType = USB_DTYPE_STRING,.wString = {CAT(u,s)}}
And CAT is a macro CAT(x,y) x##y. The intent must be to convert a string of type 8-bit char into a 16-bit Unicode type but the compiler doesn't like it. Is there some #include or compiler setting that may be missing that I have to add here? Clearly the author of this code expects it to work so there must be some fault in my setup.
Also I'm not clear on how the sizeof() operation is supposed to work here. As I understand it there is no way to get the length of a string at compile time so that operation will always return the size of a pointer.
In response to Keith's question, the gcc version is 4.2.1. Poking around the compiler settings the default option is the C99 standard, when I changed it to C11 everything compiled just fine. Thanks!

vector of boost::function not working with _placeholder

I need your help. I tried a lot to find a solution for the problem but failed so far.
Idea:
Create a vector of "command tuples" like the following:
typedef boost::tuple<std::string, boost::function<void()>> command_tuple;
std::vector<command_tuple> commands {
boost::make_tuple("command1", boost::bind(&myclass::command1, this))
};
If the string "command1" is used the void command1() function is called. The ID index value is based on find_if search for the string ("command1" is ID=0) on the vector.
This is working fine!
boost::get<1>(commands[ID])();
Problem:
I found no way so far to use a vector of boost::function (pointers) defined with any kind type of function parameters:
typedef boost::tuple<std::string, boost::function<void(const char *)>> command_tuple;
std::vector<command_tuple> commands {
boost::make_tuple("command1", boost::bind(&myclass::command1, this, std::placeholders::_1))
};
This will fail with a cannot convert std::_Placeholder<1> to type const char * compilation error.
This is therefore not possible:
boost::get<1>(commands[ID])("dynamic string argument");
Pinning down of the problem:
hmmm ... so I found out so far that even a simple vector of boost::function does not seem to work (in the way I am trying to use it):
std::vector<boost::function<void(const char *)>> commands {
boost::bind(&myclass:command1, this, std::placeholders::_1)
};
Fails with the same compilation error.
It is possible to replace the std::placeholders::_1 with "static string constants" to avoid any compilation errors. But my idea was to use a "dynamic string argument".
Can someone please give me a quick hint of what I am doing wrong or maybe show some simple alternatives. I want to have quite a big list of function pointers that I can call based on their "string name".
I simply want to avoid a big "switch select case" style code block to
select the function to be executed based on a dynamic "input string".
Thanks for your time!
like T.C. replied in the comments. You should never mix std::bind, std::placeholders and boost::bind.

Convert AnsiString to UnicodeString in Lazarus with FreePascal

I found similar topics here but none of them had the solution to my question, so I am asking it in a new thread.
Couple of days ago, I changed the format the preferences of an application I am developing is saved, from INI to JSON.
I use the jsonConf unit for this.
A sample of the code I use to save a key-value pair in the file would be like below.
Procedure TMyClass.SaveSettings();
var
c: TJSONConfig;
begin
c:= TJSONConfig.Create(nil);
try
c.Filename:= m_settingsFilePath;
c.SetValue('/Systems/CustomName', m_customName);
finally
c.Free;
end;
end;
In my code, m_customName is an AnsiString type variable. TJSONConfig.SetValue procedure requires the key and value both to be of UnicodeString type. The application compiles fine, but I get warnings such
Warning: Implicit strung type conversion from "AnsiString" to "UnicodeString".
Some messages warn saying there is a potential data loss.
Of course I can go and change everything to UnicodeString type but this is too risky. I have't seen any issues so far by ignoring these warnings, but they show up all the time and it might cause issues on a different PC.
How do I fix this?
To avoid the warning do an explicit conversion because this way you tell the compiler that you know what you are doing (I hope...). In case of c.SetValue the expected type is a Unicodestring (UTF16), m_customname should be declared as a string unless there is good reason to do differently (see below), otherwise you may trigger unwanted internal conversions.
A string in Lazarus is UTF8-encoded, by default. Therefore, you can use the function UTF8Decode() for the conversion from UTF8 to Unicode, or UTF8ToUTF16() (unit LazUtf8).
var
c: TJSONConfig;
m_customName: String;
...
c.SetValue('/Systems/CustomName', UTF8Decode(m_customName));
You say above that the key-value pairs are in a file. Then the conversion depends on the encoding of the file. Normally I open the file in a good text editor and find the encoding somewhere - NotePad++, for example, displays the name of the encoding in the right corner of the statusbar. Suppose the encoding is that of codepage 1252 (Latin-1). These are ansistrings, therefore, you can declare the strings read from the file as ansistring. Because UTF8 strings are so common in Lazarus there is no direct conversion from ansistring to Unicode, and you must convert to UTF8 first. In the unit lconvencoding you find many conversion routines between various encodings. Select CP1252toUTF8() to go to UTF8, and then apply UTF8Decode() to finally get Unicode.
var
c: TJSONConfig;
m_customName: ansistring;
...
c.SetValue('/Systems/CustomName', UTF8Decode(CP1252ToUTF8(m_customName)));
The FreePascal compiler 3.0 can handle many of these conversions automatically using strings with predefined encodings. But I think explicit conversions are very clear to see what is happening. And fpc3.0 still emits the warnings which you want to avoid...

Predefined Windows icons: Unicode

I am assigning to the lpszIcon member of the MSGBOXPARAMSW structure(notice the W). I want to use one of the predefined icons like IDI_APPLICATION or IDI_WARNING but they are all ASCII (defined as MAKEINTRESOURCE). I tried doing this:
MSGBOXPARAMSW mbp = { 0 };
mbp.lpszIcon = (LPCWSTR) IDI_ERROR;
but then no icon displayed at all. So how can I use the unicode versions of the IDI_ icons?
There is no ANSI or Unicode variant of a numeric resource ID. The code that you use to set lpszIcon is correct. It is idiomatic to use the MAKEINTRESOURCE macro rather than a cast, but the cast has identical meaning. Your problem lies in the other code, the code that we cannot see.
Reading between the lines, I think that you are targeting ANSI or MBCS. You tried to use MAKEINTRESOURCE but that expands to MAKEINTRESOURCEA. That's what led you to cast. You should have used MAKEINTRESOURCEW to match MSGBOXPARAMSW. That would have resolved the compilation error you encountered. You could equally have changed the project to target UNICODE.
But none of that explains why the icon does not appear in the dialog. There has to be a problem elsewhere. If the dialog appears then the most likely explanation is that you have set hInstance to a value other than NULL. But the code to set lpszIcon is correct, albeit not idiomatic.

Using termios in Swift

Now that we've reached Swift 2.0, I've decided to convert my, as yet unfinished, OS X app to Swift. Making progress but I've run into some issues with using termios and could use some clarification and advice.
The termios struct is treated as a struct in Swift, no surprise there, but what is surprising is that the array of control characters in the struct is now a tuple. I was expecting it to just be an array. As you might imagine it took me a while to figure this out. Working in a Playground if I do:
var settings:termios = termios()
print(settings)
then I get the correct details printed for the struct.
In Obj-C to set the control characters you would use, say,
cfmakeraw(&settings);
settings.c_cc[VMIN] = 1;
where VMIN is a #define equal to 16 in termios.h. In Swift I have to do
cfmakeraw(&settings)
settings.c_cc.16 = 1
which works, but is a bit more opaque. I would prefer to use something along the lines of
settings.c_cc.vim = 1
instead, but can't seem to find any documentation describing the Swift "version" of termios. Does anyone know if the tuple has pre-assigned names for it's elements, or if not, is there a way to assign names after the fact? Should I just create my own tuple with named elements and then assign it to settings.c_cc?
Interestingly, despite the fact that pre-processor directives are not supposed to work in Swift, if I do
print(VMIN)
print(VTIME)
then the correct values are printed and no compiler errors are produced. I'd be interested in any clarification or comments on that. Is it a bug?
The remaining issues have to do with further configuration of the termios.
The definition of cfsetspeed is given as
func cfsetspeed(_: UnsafeMutablePointer<termios>, _: speed_t) -> Int32
and speed_t is typedef'ed as an unsigned long. In Obj-C we'd do
cfsetspeed(&settings, B38400);
but since B38400 is a #define in termios.h we can no longer do that. Has Apple set up replacement global constants for things like this in Swift, and if so, can anyone tell me where they are documented. The alternative seems to be to just plug in the raw values and lose readability, or to create my own versions of the constants previously defined in termios.h. I'm happy to go that route if there isn't a better choice.
Let's start with your second problem, which is easier to solve.
B38400 is available in Swift, it just has the wrong type.
So you have to convert it explicitly:
var settings = termios()
cfsetspeed(&settings, speed_t(B38400))
Your first problem has no "nice" solution that I know of.
Fixed sized arrays are imported to Swift as tuples, and – as far as I know – you cannot address a tuple element with a variable.
However,Swift preserves the memory layout of structures imported from C, as
confirmed by Apple engineer Joe Groff:. Therefore you can take the address of the tuple and “rebind” it to a pointer to the element type:
var settings = termios()
withUnsafeMutablePointer(to: &settings.c_cc) { (tuplePtr) -> Void in
tuplePtr.withMemoryRebound(to: cc_t.self, capacity: MemoryLayout.size(ofValue: settings.c_cc)) {
$0[Int(VMIN)] = 1
}
}
(Code updated for Swift 4+.)

Resources