1

So this is my code:

// Defines a tuple
#define __WINDOW__RESOLUTION__ 500, 200 

// Seperate the tuple
#define __WINDOW__X__1(Width, Height)  (Width)
#define __WINDOW__Y__1(Width, Height)  (Height)

// Add another sort of indirection because my tuple is a macro
#define __WINDOW__X__(Macro) __WINDOW__X__1(Macro)
#define __WINDOW__Y__(Macro) __WINDOW__Y__1(Macro)

// These should be the final values 500 and 200
#define __WINDOW__RESOLUTION__X__ (__WINDOW__X__(__WINDOW__RESOLUTION__))
#define __WINDOW__RESOLUTION__Y__ (__WINDOW__Y__(__WINDOW__RESOLUTION__))

When i use the first macro where the final number should be something seems to go wrong:

std::cout << __WINDOW__RESOLUTION__X__ << std::endl; // Outputs 200 instead of 500

above line outputs the number 200, so the Y value instead of the X value

std::cout << __WINDOW__RESOLUTION__Y__ << std::endl; // ERR with macro underlined

this line won't even compile [ C2059, syntax error: ")" ]

Thank you for helping me Alex

Brogramer
  • 75
  • 8
  • 3
    [Don't use names with two leading underscores, or an underscore followed by an upper-case letter, those are reserved in all scopes](http://stackoverflow.com/questions/228783/what-are-the-rules-about-using-an-underscore-in-a-c-identifier). – Some programmer dude Jul 17 '16 at 07:05
  • 1
    As for your problem, tell your compiler to generate the preprocessed code and look at it. – Some programmer dude Jul 17 '16 at 07:07
  • 2
    I dread the day I'll find something like this in production code... You are familiar with the general guideline that use of the preprocessor should be as limited as possible, right? Why are you not simply using `const int WindowX = 500; const int WindowY = 200;`? – H. Guijt Jul 17 '16 at 07:14
  • @H. Guijt, i am still learning C++ – Brogramer Jul 17 '16 at 07:17
  • All the more reason then to step away from the preprocessor. Don't give yourself a major disadvantage by learning all sorts of bad habits before you move onto doing things the right way. See this video for more information: https://www.youtube.com/watch?v=YnWhqhNdYyk – H. Guijt Jul 17 '16 at 07:20
  • @H. Guijt I am watching it right now, but I don't really get what's the point of that course? – Brogramer Jul 17 '16 at 07:35
  • 3
    The point is that learning C++ should focus on the modern bits, which are much simpler to understand and use. It argues that beginners are much better of not getting bogged down doing hideous tricks using the preprocessor or char *-style strings or []-style arrays. While the video is not in itself a course, it should provide you plenty of pointers of what to look at first while learning the language. And if you have a book that focuses on all the C-stuff first, maybe just skip that initially. For comparison, I'm in charge of a 300,000 line C++ program that uses `#define` precisely once. – H. Guijt Jul 17 '16 at 07:53
  • @H. Guijt I got rid of the #define's now and use variables instead I am sorry for annoying with such beginner problems, but as I said I am very bad at programming I hope you can understand that – Brogramer Jul 17 '16 at 08:08
  • @H. Guijt I am curious, what does the 300,000 line program do? Because it has such a length, like is it the next star wars battlefront part? ^_^ – Brogramer Jul 17 '16 at 08:17
  • It tests spacecraft while they are still on the ground. Actually it is more like 50 separate programs working together, but I ran out of comment space so... – H. Guijt Jul 17 '16 at 15:04
  • @H.Guijt, and yet modern libraries like boost and poco find good use for the pre processor. This is especially true where text needs to be duplicated... Class and function generation. All said, I think one should use it conservatively, and the above example is a case for bad usage. – Werner Erasmus Jul 17 '16 at 16:27
  • @Brogamer Missed your earlier comment... You are not annoying. I just hate to see people learn bad habits early in their programming carreer, and hope to get you started in a much more fruitful and fun direction. – H. Guijt Jul 17 '16 at 17:02

2 Answers2

2

For the record - I understand that your solution is "do not do this", but I still wanted to provide an answer for the original question.

In fact, I actually don't see anything wrong with your code. It actually works fine if you compile it with a basic test example like this one:

// Defines a tuple
#define __WINDOW__RESOLUTION__ 500, 200 

// Seperate the tuple
#define __WINDOW__X__1(Width, Height)  (Width)
#define __WINDOW__Y__1(Width, Height)  (Height)

// Add another sort of indirection because my tuple is a macro
#define __WINDOW__X__(Macro) __WINDOW__X__1(Macro)
#define __WINDOW__Y__(Macro) __WINDOW__Y__1(Macro)

// These should be the final values 500 and 200
#define __WINDOW__RESOLUTION__X__ (__WINDOW__X__(__WINDOW__RESOLUTION__))
#define __WINDOW__RESOLUTION__Y__ (__WINDOW__Y__(__WINDOW__RESOLUTION__))

#include <iostream>
using namespace std;

int main() {
    // your code goes here
    std::cout << __WINDOW__RESOLUTION__X__ << std::endl;
    std::cout << __WINDOW__RESOLUTION__Y__ << std::endl;
    return 0;
}

It looks like your error may be related to the brackets in your last macro, though, so just removing them could possibly solve that, but again - this wasn't required for me (using gcc 5.4 under ubuntu):

// These should be the final values 500 and 200
#define __WINDOW__RESOLUTION__X__ __WINDOW__X__(__WINDOW__RESOLUTION__)
#define __WINDOW__RESOLUTION__Y__ __WINDOW__Y__(__WINDOW__RESOLUTION__)

It was previously also pointed out that double underscore __ followed by an upper-case letter is reserved, but it certainly didn't stop gcc from compiling this - maybe it would generate an error with stricter compile flags, though!

Chris
  • 3,245
  • 4
  • 29
  • 53
  • Thank you for helping me Chris, I really appreciate the fact you're helping me out since it is a do-not-do. I don't know, but before I can focus do's and dont's i have to learn the language and you just helped me getting one step closer to accomplish that, so thank you very much! ^_^ – Brogramer Jul 17 '16 at 09:03
  • 1
    Well, you know, people have their preference what should / shouldn't be done, but it's not always up to you (alone) how the code looks like that you are working with, right? It would be good to know which compiler you were using on what platform, though – Chris Jul 17 '16 at 09:08
  • Also you should mention `using namespace std;` is a b ad idea – Ed Heal Jul 17 '16 at 09:59
  • Especially, if you then go on to write `std::cout` anyway :D – Chris Jul 17 '16 at 10:00
2

It seems to work fine when compiled with gcc4.9, but the problem might lie in that the compiler threads __WINDOW__RESOLUTION__ as a single parameter. For example, if you replace

#define __WINDOW__RESOLUTION__X__ (__WINDOW__X__(__WINDOW__RESOLUTION__))

with

#define __WINDOW__RESOLUTION__X__ (__WINDOW__X__(500, 200))

It will throw an error because __WINDOW__X__ expects only 1 parameter.

You can solve this by using ... and __VA_ARGS__ in your macro, which will forward any parameter that it receives:

#define __WINDOW__X__(...) __WINDOW__X__1(__VA_ARGS__)
#define __WINDOW__Y__(...) __WINDOW__Y__1(__VA_ARGS__)
Morris Franken
  • 2,435
  • 3
  • 19
  • 13