concat macro

Feb 4, 2009 at 7:25am
Hi programmers!

I'm wanting to know how, if there is a way, to "build" variables through a loop. I'm not interested in using an array. This is an example of what I'm trying to do:

1
2
3
4
5
#define concat(a, b) a ## b
...
int a1, a2, a3;
for (int i = 1; i <= 3; ++i)
  concat(a, i) = i;


My macro is broken. You can see how it tries to create variable "ai" instead of "a" with the value of "i". Is there a way to get this concat macro working so that it is effectively replaced with a1, a2, then a3 through the loop?

Thanks.

~psault
Feb 4, 2009 at 10:28am
As you may already know, the preprocessor runs at compile time (before the compiler) and your macro is dependent on runtime symbols. You need a way to determine the range of your loop at compile time for a start.

The C++ way would be to resort to Template Metaprogramming as described in Modern C++ Design by Alexandrescu (http://books.google.co.uk/books?id=aJ1av7UFBPwC&dq=modern+c%2B%2B+design&printsec=frontcover&source=bn&hl=en&sa=X&oi=book_result&resnum=5&ct=result).
Feb 4, 2009 at 12:38pm
Yes, boost::mpl will provide you the tools you need to implement a for-loop at preprocessing time, however it has a steep learning curve.

What is it you need to do?
Feb 4, 2009 at 5:04pm
It looks like an STL container is in order...
Feb 4, 2009 at 7:00pm
+1 seymore:

1
2
3
4
map<string, int> values;

for (int i = 1; i < 4; ++i)
 values["var" + i] = i;


Obviously, you will have to handle type-conversion from i to string. But that'll work fine.
Feb 5, 2009 at 1:36am
I'm really just playing around, but what I wanted to achieve is something like this code, only without the need for the switch.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
#include <iostream>

#define concat(a, b) a ## b

void Func1();
void Func2();

int main()
{
  void (*pFunc)();
  for (int l = 0; l < 10; ++l) {
    for (int i = 1; i <= 2; ++i)
    {
      switch (i) {
        case 1:
          pFunc = concat(Func, 1);
          break;
        case 2:
          pFunc = concat(Func, 2);
          break;
      }
      pFunc();
    }
  }
  system("pause");
}

void Func1()
{
  std::cout << "Function 1" << std::endl;
}

void Func2()
{
  std::cout << "Function 2" << std::endl;
}


~psault
Feb 5, 2009 at 12:04pm
You could just make a table of function (pointers) and use the i to index into the table.
Feb 5, 2009 at 4:26pm
Make a base class with a virtual method, inherit from it for each of your implementations, construct the appropriate object in main, and just call the method. Polymorphism: the C++ way to do that.
Last edited on Feb 5, 2009 at 4:26pm
Feb 5, 2009 at 10:29pm
Thanks for the suggestions. I will research the potential of them in my programs.

~psault
Feb 5, 2009 at 10:44pm
Yes, an std::map<int, void(*)()> seems perfect for this.
Topic archived. No new replies allowed.