hi all,
i'm miffed as to why this doesn't work. i get about 20 compile errors
when i compile, which aren't helping.
i think you should be able to see what i'm trying to do but can you help me with how to do it properly ?
1 | |
2 | #define LARGEST_SHADING_CIRCLE_DIAMETER 520 |
3 | #define SMALLEST_SHADING_CIRCLE_DIAMETER 192 |
4 | #define DIAMETER_DECREMENT =\ |
5 | (LARGEST_SHADING_CIRCLE_DIAMETER - SMALLEST_SHADING_CIRCLE_DIAMETER)\ |
6 | /10 |
7 | |
8 | int circle_sizes[10] = { |
9 | LARGEST_SHADING_CIRCLE_DIAMETER, |
10 | LARGEST_SHADING_CIRCLE_DIAMETER - (1 * DIAMETER_DECREMENT), |
11 | LARGEST_SHADING_CIRCLE_DIAMETER - (2 * DIAMETER_DECREMENT), |
12 | LARGEST_SHADING_CIRCLE_DIAMETER - (3 * DIAMETER_DECREMENT), |
13 | LARGEST_SHADING_CIRCLE_DIAMETER - (4 * DIAMETER_DECREMENT), |
14 | LARGEST_SHADING_CIRCLE_DIAMETER - (5 * DIAMETER_DECREMENT), |
15 | LARGEST_SHADING_CIRCLE_DIAMETER - (6 * DIAMETER_DECREMENT), |
16 | LARGEST_SHADING_CIRCLE_DIAMETER - (7 * DIAMETER_DECREMENT), |
17 | LARGEST_SHADING_CIRCLE_DIAMETER - (8 * DIAMETER_DECREMENT), |
18 | SMALLEST_SHADING_CIRCLE_DIAMETER |
19 | }; |
compile errors available if wanted.
compile errors available if wanted.
Duh.
I'm guessing wildly here, that the compiler doesn't like the ides of you initially constructing the array with values that have to be calculated or something? I have no idea, really.
Your DIAMETER_DECREMENT declaration looks a bit suspect. I really do hate macros ...
int circle_sizes[10] = { LARGEST_SHADING_CIRCLE_DIAMETER,
That happens at compiling time and the compiler doesn't calculate stuff like:
LARGEST_SHADING_CIRCLE_DIAMETER - (1 * DIAMETER_DECREMENT),
or does it?
Lose the '=' in the third macro.
yeah that's probably it i guess.
can't see why a compiler can't add a few ints together tho'
it's nicer for me because this way facilitates easily trying different values.
i'll swap the sc's for numbers and see if it's more digestable
Lose the '=' in the third macro.
will do
noone mentioned it being wrong earlier when i posted that
code on 'simple C question' thread.
(i shouldn't use your brains as my compiler i suppose )
i thought the '=' was out of place (no other defines need one)
hope it works..
can't see why a compiler can't add a few ints together tho'
Can't see why you can't declare your macro properly (and really, the only way to properly define a macro is to use something else. )
All three could be const int's, since the third macro only gets calculated once and doesn't change anyway ...
I'm guessing wildly here, that the compiler doesn't like the ides of you initially constructing the array with values that have to be calculated or something?
Since the resulting value can be arrived at at compile-time, where's the problem?
How much can a compiler calculate? I've never used anything else than constants in that kind of code lines.
[OT] Cheer up, Marvin:
http://edu.loviisa.fi/~jhalmen/images/marvin.jpg
That's better
Any compiler worth its salt will optimize constant operations together into a single constant when compiling. So if you type "640 - 43" in code, it won't actually do a subtraction whenever that's used; the compiler will just put the constant 596 in the program instead.
If you want a taste of what is possible, do a search for "template metaprogramming".
[EDIT]
Any compiler worth its salt will optimize constant operations together into a single constant when compiling. So if you type "640 - 43" in code, it won't actually do a subtraction whenever that's used; the compiler will just put the constant 596 in the program instead.
Thank you, Captain Obvious. Why do you think only computations involving constant values are allowed in standard code?
[/EDIT]
Since the resulting value can be arrived at at compile-time, where's the problem?
I didn't see one; that's why it was a wild guess. I saw the '=' later.
Rash: The pseudo-Finn asked, so I answered.
#define LARGEST_SHADING_CIRCLE_DIAMETER 520 #define SMALLEST_SHADING_CIRCLE_DIAMETER 192 #define DIAMETER_INCREMENT ((LARGEST_SHADING_CIRCLE_DIAMETER - SMALLEST_SHADING_CIRCLE_DIAMETER) / 10) #define CIRCLE_SIZE(a) (SMALLEST_SHADING_CIRCLE_DIAMETER + a * DIAMETER_INCREMENT )
This should work ok. Note that I got CIRCLE_SIZE() backwards, but I found that more readable (0 is smallest, 10 biggest)
edit: what, macros are bad?
Good, bad, I'm the guy with the gnu.
You know, this thread perfectly shows why macros are pure evil. Make a mistake in declaring one, see the mistake somewhere else.
Make a mistake in declaring one, see the mistake somewhere else.
That is so very annoying.
Here's the only cool use of macros:
// arthurmath.cpp #include <iostream> #define SIX 1 + 5 #define NINE 8 + 1 int main() { std::cout << SIX * NINE << std::endl; }
Hey, I may have a roundoff error, but I did surround my numerical expressions with braces.
make it
#define MAX_RADIUS 520 #define MIN_RADIUS 192 #define CIRCLES 10 #define CIRCLE(a) ( (MAX_RADIUS - MIN_RADIUS) * (a) / CIRCLES + MIN_RADIUS )
Macros are evil. Use const for variables, inline functions for functions. Macros are evil. Macros are evil. evil
Geez. Since when are macros evil?
You just have to know when to use them.
Yes, I agree with gillius. Even if you bypass the const protection, the code at runtime will crash.
You just have to know when to use them.
Which is not oftern. 19 times out of 20, there's a better way to accomplish what you're doing. I don't use macros unless I can't find some other safer/faster/easier option ... and I usually can ...
As long as there's no way to replace the # and ## macro operations, there's a need for defines. It's that easy.
Not familiar with what you mean. And bluntly, it's definitely not relevant to the code in the original post.
I never said macros are useless. I also never said they should never be used. They are just evil. All preprocessor stuff is evil, including the header guards. An evil can be a necessary evil. Now, in this case, I think he should be using const variables and not defines.
OT: 23, # is the stringtificator(sp?) operator, converting the parameter of a macro into a string, while ## is the concatenator, in case you didn't know
How often do you use MIN, MID and MAX? I find them very useful.
All preprocessor stuff is evil, including the header guards.
Why is that?
Not familiar with what you mean
The # operator puts it's operand in quotes.
#define DEBUG_CASE(value) case value: log(#value) enum { ERROR_SOMETHING }; switch (returnCode) { DEBUG_CASE( ERROR_SOMETHING ) // your code here break; }
will evalute into:
enum { ERROR_SOMETHING }; switch (returnCode) { case ERROR_SOMETHING: log("ERROR_SOMETHING"); // your code here break; }
You can also use it to create string representations for your constants:
1 | // events.h |
2 | EVENT( MSG_PlayerHit ) |
3 | EVENT( MSG_EnemySpawned ) |
4 | |
5 | // events.cpp |
6 | #define EVENT(msg) msg, |
7 | enum Events { |
8 | #include "events.h" |
9 | }; |
10 | #undef EVENT |
11 | #define EVENT(msg) #x, |
12 | |
13 | static const char* EventStrings[] = { |
14 | #include "events.h" |
15 | }; |
16 | #undef EVENT |
You can also use it if you're too lazy to write your own embedded language parser. I used the preprocessor to create a little "embedded language" so createing the JS interface is more easy.
I could have written something like luaBind, but why should I? The cpp is tried and proven and works perfectly well
So, code like this:
GetterStart GetterAttributesStart Get( width ) // return width as JS var Get( height ) // return height as JS var GetterAttributesEnd GetterEnd
Is translated into the correct interface calls:
1 | JSBool gimlJSImageGetFunc(JSContext *jsContext, JSObject *thisObj, jsval id, jsval *vp) { |
2 | JSBool result = JS_TRUE; |
3 | |
4 | if (JSVAL_IS_INT(id)) { |
5 | switch(JSVAL_TO_INT(id)) { |
6 | case 0xEfffffff: { |
7 | } |
8 | case GIML_JS_IMG_WIDTH: { |
9 | // return width as JS var |
10 | } break; |
11 | case GIML_JS_IMG_HEIGHT: { |
12 | // return height as JS var |
13 | } break; |
14 | } |
15 | } |
16 | } |
The Image and IMG parts are of course dynamic
So I didn't had to write a special parser. And writing interface code got more readable.
I got that idea from an artcile in Game Programming GemsI, where a complete state machine was developed that way. You should check it out, the resulting code is quite neat.
I got that idea from an artcile in Game Programming GemsI, where a complete state machine was developed that way. You should check it out, the resulting code is quite neat.
Not sure I curently have need for such a thing, but it's not like I can afford any of the GPG books anyway.
spellcaster, it is useful, but when you create complex macros like in MFC, you are abusing the language features Especially if you add bunch of code in a macro.
spellcaster, it is useful, but when you create complex macros like in MFC, you are abusing the language features
If it saves me several days of coding and testing, is more easy to read and doesn't require any new utilities, it's not abuse.
Esp. not since the preprocessor was made to do that job. I'm not abusing it, I'm using it.
I agree that inline functions and constants / enums should be used where it is possible. But if you want to output a linenumber, you should better use the _LINE_ macro
Know your tools, and use them well. That includes cpp.
Sure, but having something like this is evil:
int main() { INITIALIZE_ALLEGRO(); PLAY_GAME(); TERMINATE_ALLEGRO(); } END_OF_MAIN()
No, making a game almost entirely out of templates is evil.
As long as there's no way to replace the # and ## macro operations, there's a need for defines. It's that easy.
spellcaster, you're seriously pissing me off with this straw man. 95% of all instances of macros I ever saw at Allegro.cc were unjustified and then you bring up a few exotic uses of it where it might be useful supposedly as a rebuttal?
I stand by the statement that macros should be minimized AS MUCH AS POSSIBLE and so should you. Frankly, you're not helping changing the general mindset here.
spellcaster, you're seriously pissing me off with this straw man
Who's strawmanning here, eh? Allegro's use of macros was not mentioned once prior to spellcaster saying that line, and he didn't mention it either.
EDIT: For the record, Rash's post said "... I ever saw in Allegro ..." before he edited it. Not that it matters; the topic of "95% of instances of macros on Allegro.cc" wasn't brought up either. One broad statement was made, and a casual comment was made disfavoring that statement. Someone needs to lay off the alkaloids...
I already mentioned MIN, MID, MAX are useful to me. So what's wrong with using them?
I already mentioned MIN, MID, MAX are useful to me. So what's wrong with using them?
Inlined versions are safer. A Google for the MIN macro (just for the sake of double checking what I was about to say) coughs up "MIN macro in numbers.c causes build problems on HP-UX" as the first hit.
Fourth hit demonstrates some problems ("In this small example you can already see several of the dangers of macro arguments ...")
Macros have uses, but very specialized ones. For the purposes of this discussion, in regards to the above code, macros are evil.
These are the same as those defined by allegro?
The MIN() macro is pretty much the same everywhere ...
#define min(X, Y) ((X) < (Y) ? (X) : (Y))
Makes me sick, it does. An inlined template function is much better.
IMHO, of course ....
DJGPP has another, using the __typeof to prevent errors this macro has.
looks ok to me.
a = MIN(--b, ++c);
Depending on whether you're using the macro or an inlined function, you'll get two different results for 'a'.
EDIT: The "expensive_computation" argument is another good one ...
looks ok to me.
min(expensive_computation(), another_expensive_computation())
...after cpp...
(expensive_computation() < another_expensive_computation() ? expensive_computation() : another_expensive_computation())
Just one example of why it's evil. Either way the "winner" is going to have to be executed twice. If either has side effects, you're even further up sh*t creek...
int a = 9; int b = 10; int c = 0; c = MIN(a++, b);
Should return 9, returns 10.
ok.. it is 12:40am here.
But what about normal variables:
c = MIN(a, b);
any problems here?
looks ok to me.
The fact this comment got thrice bum-rushed tells you this is a classic example of evil macros.
any problems here?
There? No. But wouldn't you prefer a function that NEVER gives you problems? See the first post; you can shoot yourself in the foot reall easy like ...
Or... unsensible use of the macro.
Should return 9, but returns 10.
unsensible use of the macro
Just by making it an inline function instead, this kind of misbehaviour is made impossible. You don't have to care any more, and the function will execute just as fast. Why give you the chance to shoot yourself in the foot if preventing it is just as powerful?
Or... unsensible use of the macro.
Would you consider it better practice to make bulletproof code that always works, or code that relies on you not to screw it up every time you reference it? The macro has pitfalls, and zero advantages over the inlined template function.
spellcaster, you're seriously pissing me off with this straw man. 95% of all instances of macros I ever saw at Allegro.cc were unjustified and then you bring up a few exotic uses of it where it might be useful supposedly as a rebuttal?
I think I got that covered, eh?
I agree that inline functions and constants / enums should be used where it is possible.
I think you should apologize. And maybe you should read the posts you're replying to, and maybe even think twice before you post once. Just an idea.
Anyway, saying that macros are "evil, evil, evil" is singleminded. And not very clever. Due to the idea that all a macro can do is just text replacement, nobody cares about the cpp anymore. Most don't even know about the # and ## operators and how to use them.
But, from time to time macros are extremly useful, make your code more easy to read and more easy to maintain.
unsigned char flags = BINARY2( 1001, 0011);
is more easy to read and less error prone than the decimal or hexadecimal version of that number.
assertmsg( value > 0, "The value must be > 0");
will give you a better error message than a pure assert().
Macros allow to create a string containing both file name and line number... which is quite neat, IMO.
The point is: cpp is a tool. If you use it wisely, it'll help you. If you use it poorly, well, than you're not clever enough.
Always use the right tool for the right job. Should one use a #define for constants or should one prefer enums or consts? In that case the define looses.
Samething for macros and inline functions (most of the time).
But: Just because there are better ways for these two jobs doesn't mean that "macros are evil". And whoever telling you that macros are evil never read the cpp description
All it means that you shouldn't use macros for constants and inline methods. It's as easy as that.
<shrugs>
I only use it as: c = MIN(a, b); anyway.
And on that note, I'm off to bed. If I can sleep in this stifling heat..
EDIT: For the record, Rash's post said "... I ever saw in Allegro ..." before he edited it.
You must be imagining things, because I did no such thing.
Ten to one this thread will now degenerate into a C vs C++ vs C99 discussion...Oh wait!
All it means that you shouldn't use macros for constants and inline methods. It's as easy as that.
Right. But that's what most people use them for, like it or not. Like, you know, above. Remember this post? Teach the acolyte that macros are evil. When he is a wizard, he can use the black magic when necessary.
William Labbett: MACROS AER TEH EVAL!!1 RUNRUNRUNRUN ...
Teach the acolyte that macros are evil.
That's not needed. Teach everybody that he should use consts and enums for constant values, and inline functions for inline functions.
That's it. No black magic involved here.
EDIT:
Rash: I either want your macro less way for the normal uses of # and ## inside macros, or an apology...
On the other hand, no apology and no macro less way would prove my point as well
Here's a great opportunity to mold a young mind... How would an inlined template-using MIN look? (i have no idea how templates work, but im sure it can be useful )
I assume something like:
inline template <typename T> T min(T a, T b) { return (a < b ? a : b); }
EDIT: Forgot return type.
Off the top of my head ...
template<class T> inline T cadd(T x, T y) { return (x < y ? x : y); }
I might have goofed; it's untested ...
EDIT: All fixed.
Ok, to stay in character I'll make my 1000th post useful:
#include <algorithm> std::min(a,b);
[EDIT]
No need to reinvent the wheel, is there?
[/EDIT]
X-G: Your code didnt compile.
23: your code worked after i replaced X with z1 and Y with z2
No need to reinvent the wheel, is there?
No need to include a standard header for four lines, either. He did ask to see what it would look like ...
23: your code worked after i replaced X with z1 and Y with z2
Whoops; right. That's what I get for copying off of Google.
All fixed.
X-G: Your code didnt compile.
How about telling me WHY? Mine is identical to 23's, apart from the placement of "inline" and line breaks/parentheses that shouldn't matter...
I think it's the inline placement, X-G ...
I dont know WHY, but im sure this can help
1 | g++.exe -c main.cpp -o main.o -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" |
2 | |
3 | main.cpp:5: error: syntax error before `<' token |
4 | main.cpp:8: error: definition provided for explicit instantiation |
5 | main.cpp:8: error: non-template used as template |
6 | main.cpp:8: error: syntax error before `{' token |
7 | main.cpp:12: error: ISO C++ forbids declaration of `system' with no type |
8 | main.cpp:12: error: `int std::system' redeclared as different kind of symbol |
9 | C:/Dev-Cpp/include/stdlib.h:362: error: previous declaration of `int |
10 | system(const char*)' |
11 | main.cpp:12: error: invalid conversion from `const char*' to `int' |
12 | |
13 | main.cpp:13: error: syntax error before `return' |
14 | |
15 | C:/Dev-Cpp/include/c++/3.3.1/iostream:77: error: definition provided for |
16 | explicit instantiation |
17 | C:/Dev-Cpp/include/c++/3.3.1/iostream:77: error: non-template used as template |
18 | C:/Dev-Cpp/include/c++/3.3.1/iostream:77: confused by earlier errors, bailing out |
Rash: I think my point is proven then, eh?
main.cpp:5: error: syntax error before `<' token
Err, excuse me? That's where "template" is at. Well, considering how vague errors can be some times, let's just assume it's the placement of the word "inline".
yeah, worked when i moved it.. (template <typename T> inline T min(T a, T b) { return (a < b ? a : b); })
Make the return value a reference and you'll have nailed it.
spellcaster: http://www.parashift.com/c++-faq-lite/big-picture.html#faq-6.14
Make the return value a reference and you'll have nailed it.
Return a reference? I can see the parameters as references, but by constructing the object right on the return statement ... well, I didn't know you could beat that. I might be wrong, but what are we returning a reference to?
BTW, that is the coolest new entry into the C++ FAQ Lite ever.
Well in that case make the parameters references as well. The declaration of std::min, after all, is:
template <class T> const T& min(const T& a, const T& b);
rash: what's your point?
Please read your own post. Then my reply.
Then think.
You even quoted me saying that there are uses for macros. Then you replied that this "pisses you off".
I guess this means that you either have a better way to handle these situations, or that you either impolite and/or challenged by the concept of independent thought, and thus need to repeat the old dogmas ("Macros are evil, sha-la-la-la").
While I can understand the latter, you've still been rude
Wouldn't it be hard to create an inline min() that handles floats, doubles, chars, and ints, without using C++? That's one of the problems I had with my game, I had inline min()/max() functions, but they were messing up because it took ints, but I was passing floats (though I wasn't initially aware of this). I changed them to defines like Allegro has and now it works hunky-dory.
Though I do kinda wish the inline functions worked.. branchless min/max is a good thing to have.
KC, you could send a third parameter stating the type of the parameters you are sending. As for creating one, this is how DJGPP defines it:
#define min(X, Y) \ ({ typeof (X) __x = (X), __y = (Y); (__x < __y) ? __x : __y })
You know you use too much macros, when you demand syntax hilightning in them.