1

I am trying to figure out how to write a macro that will append value of a variable to a string. Here is a snippet of non working code but I am showing it so that I can explain what I want to do

#include <iostream>
#include <string>
#include <sstream>

using namespace std;

#define  DATA_RESPONCE_0 23
#define  DATA_RESPONCE_1 24
#define  DATA_RESPONCE_2 25
#define  DATA_RESPONCE_3 26

#define my_macro(x) DATA_RESPONCE_##x


int main() {

    int i = 0;
    int k;

    k = my_macro (i);

    cout << k;

    return 0;
}

In this case the macro is expanded as DATA_RESPONCE_i but I want it to be DATA_RESPONCE_0 so that 23 should be printed as a value of k.

Sourav Ghosh
  • 133,132
  • 16
  • 183
  • 261
  • 5
    No, you can't do that – Danh Jan 05 '17 at 08:00
  • 11
    [XY Question](http://meta.stackexchange.com/questions/66377/what-is-the-xy-problem). Why do you think you need to do it this way? – StoryTeller - Unslander Monica Jan 05 '17 at 08:01
  • 3
    The closest would be to make `DataResponse` an array (not macros), and use `DataResponse[i]`. – Bo Persson Jan 05 '17 at 08:02
  • 2
    You should look at [How to concatenate twice with the C preprocessor…](http://stackoverflow.com/questions/1489932/). However, you're trying to use a variable set at runtime in the preprocessor which mainly works with constants at compile time. If you want to use `my_macro(0)`, then you could use the techniques in that question to get the result you want. Using a variable like `i` isn't going to work. – Jonathan Leffler Jan 05 '17 at 08:04
  • Macros are expanded by the preprocessor. The value of the variable won't be known until runtime, so of course the preprocessor cannot access it. – Mad Physicist Jan 05 '17 at 08:06
  • You could make a `DATA_RESPONSE` macro that takes a parameter – bruceg Jan 05 '17 at 08:17
  • @MadPhysicist: Oh? What about ... wormholes? Or for that matter, thinking pythonic about it, what about Guido's time machine? – Cheers and hth. - Alf Jan 05 '17 at 11:06
  • pre-processor doesn't know anything about `i` it's not the compiler. – Raindrop7 Jan 05 '17 at 11:28
  • 1
    @Raindrop7 compiler doesn't know about the value either. That's the runtime. – Mad Physicist Jan 05 '17 at 13:46
  • @Cheersandhth.-Alf I don't think the OP has reached the skill level to tell his preprocessor about wormholes yet. All in due time, for now. – Mad Physicist Jan 05 '17 at 13:48

2 Answers2

6

You can't do it with a macro. Preprocessing (which is when macros are expanded) is the first step of compilation. Long before the value of i can possibly be known.

If you intend to map a run time value to something, use a proper function:

int my_function(int x)
{
  static const int map[] = {
    DATA_RESPONCE_0,
    DATA_RESPONCE_1,
    DATA_RESPONCE_2,
    DATA_RESPONCE_3
  };

  assert (x >= 0 && x < sizeof(map)/sizeof(map[0]));
  return map[x];
}

I used the assert macro, since you seem to want hard failure when x isn't a valid value.


On a closely related topic. Unless your macros inhabit a header which is included by both C and C++ code, prefer the C++ style of defining constants:

enum class data_response { // Properly scoped. 
  type_0 = 23,
  type_1, // Consecutive values are used after 23. No need to specify 24
  type_2,
  type_3
};

The properly scoped enum class will lower the amount of pollution to the global namespace. And can even be further namespaced itself. It is superior to macros which cannot be made to respect namespaces or scoping.

data_response my_function(int x)
{
  static const data_response map[] = {
    data_response::type_0,
    data_response::type_1,
    data_response::type_2,
    data_response::type_3
  };

  assert (x >= 0 && x < sizeof(map)/sizeof(map[0]));
  return map[x];
}
StoryTeller - Unslander Monica
  • 165,132
  • 21
  • 377
  • 458
0

Macros are expanded at compile time. The values of variables at some given point of time in some given execution of some given process of the program, later on, isn't known at compile time. So, the macro can't do the job.

Since you reportedly have severe memory constraints, just replace

k = my_macro (i);

with

k = i + 23;

There.


If the “data response” values need to be more arbitrary, consider using an array:

int const data_response[] = {23, 25, 25, 82};
k = data_response[i];

An alternative is to use a switch statement, but it may use more memory.


If the values of i can be non-consecutive then you need to make some engineering decision about memory usage versus code complexity versus the need for this value at all. For example, a std::map can technically be a solution but in a tight memory situation it might very far from ideal.

Cheers and hth. - Alf
  • 142,714
  • 15
  • 209
  • 331