# Macro problem (C++, VC6)

This topic is 4188 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

## Recommended Posts

I'm using a macro defined as such:
#define PROPERTY_EDIT(theVar, theLabel, theDesc) if (bInit)
{
CPropItem item;
item.Type = 0;
item.Label = theLabel ;
item.Description = theDesc ;
Items.push_back(item);
}
else
{
if (SLabel == theLabel )
{
eData-> theVar = szValue;
}
}


Edit: I've got backslashes to escape the end of each line there, but it seems to mangle the formatting Then I use it like so:
PROPERTY_EDIT(m_Text, "bob", "Description");
However I get the following errors pointing to that line:
error C2065: 'm_Text' : undeclared identifier
error C2501: 'PROPERTY_EDIT' : missing storage-class or type specifiers
error C2078: too many initializers
error C2440: 'initializing' : cannot convert from 'char [12]' to 'int'
Weirdest is why the hell is it converting the "Description" string to an integer?? If I paste the code of what I'd expect it to expand to, this compiles fine without any problems:
	if (bInit)
{
CPropItem item;
item.Type = 0;
item.Label = "bob";
item.Description = "Descriptive text";
Items.push_back(item);
}
else
{
if (SLabel == "bob")
{
eData->m_Text = szValue;
}
}


I cannot figure this one out, can someone show me whats wrong? Cheers

##### Share on other sites
Got the books open, I'm working through it... bare with me...

EDIT: I'm still looking through it. Looks fine to me at the moment, checking a few more possibilites. However, this is an excerpt from "Practical C++":

WHEN TO USE MACROS

Macros can be useful for eliminating tedious, repetitive typing, and they are very important in C programming, but they have much less usefulness in C++ programming. Because macros reorganize source code text before the compiler sees it, they can cause problems that aren't readily apparent. In short, it's good to know how to create and use a macro, but don't use one unless you thinkn you have to.

##### Share on other sites
I'm not sure why this isn't working for you off the top of my head, but may I suggest that use write a function for this instead of trying to make it into a macro? I believe that would be better in this situation. (unless you have a specific reason for not wanting to use a function)

##### Share on other sites
I am going to have to agree with Svenjamin, a function to execute this code would definitely be more efficient here. I can't figure out what is wrong with the code, and I'm sure it's some very wierd problem. Make sure that when expanding macros on multiple lines, each backslash is followed by a hard return, and that there is no backslash on the last line in the macro (i.e)

EDIT: I see what you mean about the backslash problems... ah well, I think you get the point.

Lastly, try surrounding the entire macro in curly braces (i.e. { if(bInit) ... }})

That may work, other than that, I'd really suggest a function instead.

##### Share on other sites
Hey i'm working on this project with Ash, the reason it really would be incovenient to be a function is because this is an SDK, and each 'PROPERTY_XXX', in this case 'EDIT' are in a sort of property map.

It'd be really good if someone could try compiling this in VS 2005 and seeing if it's a VC6 error, or something else

Thanks

##### Share on other sites
I have VS2005 in which I could compile it, however, I don't have the definitions of the classes that are used, or the code preceeding and following this code. How large is the source at the moment?

EDIT: I'll see if I can't create an empty class with similar names and try that.

##### Share on other sites
Nah, I'm going to need the source, atleast the definitions of CPropItem, Items, eData, etc... all the stuff contained in the sample. However, running that code alone, all I'm getting are "Undeclared Identifiers", which means the macro may be working fine under VS2005

##### Share on other sites
Thanks for giving it a go, here are the simplified definitions:

class editTime
{
public:
EINFO* objectData;
};

struct EINFO
{
CString m_Text;
};

struct CPropItem
{
int Type;
CString Label;
CString Description;
};

a test set of using the macro:

BEGIN_PROPERTY_TABLE();
PROPERTY_EDIT(m_Text, "A", "B");
END_PROPERTY_TABLE();

and the entire macro:

#define BEGIN_PROPERTY_TABLE() void WINAPI ETOnPropertyChanged(editTime* editObject, LPCSTR szLabel, LPCSTR szValue, bool bInit, vector& Items) { CString SLabel = szLabel;
#define PROPERTY_EDIT(paramV, paramL, paramD) if (bInit) { CPropItem item; item.Type = 0; item.Label = paramL ; item.Description = paramD ; Items.push_back(item); } else { LPEINFO eData = editObject->objectData; if (SLabel == paramL ) { eData-> paramV = szValue; } }
#define END_PROPERTY_TABLE() CPropItem End; End.Type = -1; if (bInit) Items.push_back(End); } \

##### Share on other sites
There are two separate issues here: one, you're using VC6, and two, you're using macros. Fix the former first, it'll be easier, and may make fixing the latter unneccessary.

CM

##### Share on other sites
Do you have the definition, or know the include file for CString?

##### Share on other sites
Make sure your "TEST SET OF MACROS" is after the #defines, also remove the backslash at the end of the last define.

This, for me, got rid of the errors that showed up, that were similar to yours (i got a bunch more because I didn't have CString and stuff. Tell me if that fixes it, or if you even have it in that order.

EDIT: Added the MFC functions to my code, now have CString running, a few more errors to sort out, and it should be working.

[Edited by - F1N1TY on September 7, 2006 12:21:42 PM]

##### Share on other sites
Definitely make sure this code:

BEGIN_PROPERTY_TABLE();PROPERTY_EDIT(m_Text, "A", "B");END_PROPERTY_TABLE();

Comes AFTER the macro definitions (#define). That's the only reason it generates those errors for me.

Also, there's no need for the paranthesis after BEGIN_PROPERTY_TABLE and END_PROPERTY_TABLE if it doesn't take paramaters, and it's just a macro. See if this fixes your problem, I hope it does.

##### Share on other sites
KISS: Keep It Simple, Stupid

How to write macros that won't drive you batty 101.

1> If you can, do it in a function.
Change PROPERTY_EDIT to be a one-line macro that calls a function, passing in parameters.

Now compilation errors in the code will make sense, and you can even debug without doing it in disassembly!

2> Baby steps
Start with a simple macro that has a similar structure, and does something simple like "hello world".

Work your way up one step at a time by making your macro code a touch more complex at each stage. Use source control to check in your code whenever you make it do something new, so you can compare and roll back your mistakes.

...

#2 you'll have to do yourself. #1 I can do for you:
template<typename T, typename U, typename ItemsType>inline void DoPropertyEdit(  bool bInit,  char const* theLabel,  char const* theDesc,  T* theVar,  U szValue,  ItemsType& Items){	if (bInit) {		CPropItem item;		item.Type = 0;		item.Label = theLabel ;		item.Description = theDesc ;		Items.push_back(item);	} else {		if (SLabel == theLabel )		{			*theVar = szValue;		} 	}}

Now we change PROPERTY_EDIT:
#define PROPERTY_EDIT(theVar, theLabel, theDesc) \   DoPropertyEdit(bInit, theLabel, theDesc, &(eData->theVar), szValue, Items);

(note I inserted a space after the slash in the above macro -- you'll have to fix that if you copy/paste).

This minimizes the amount of complex code that happens within your macro. Debugging macros (both compile-time failure and run-time failure) is a bitch, so don't do it.