Search code examples
c++cmakec-preprocessorpreprocessorpreprocessor-directive

How to dynamically expand a variable in CPP


#include <iostream>
using namespace std;

const string getFileNameAsVarName(string filename, int lineNo)
{
  string s = "";
  for (char c : filename)
  {
    if (c > 'a' && c < 'z')
    {
      s += c;
    }
  }
  return s + to_string(lineNo);
}
#define DYNAMIC_NAME() (getFileNameAsVarName(__FILE__, __LINE__))
#define NAME() aaa

int main()
{
  int NAME() = 123; // OK Expands to: aaa
  int DYNAMIC_NAME() = 234; //Not OK Expands to: 
  // (getFileNameAsVarName("/Users/guichizhao/Documents/GitHub/learn/main.cpp", 29))
  return 0;
}

It may look wired, but we have a valid use case. Our intention is to declare a dynamically named variable i.e. The variable name is determined by the filename and lineNo, We try to achieve this by using a macro, it seems the only chance we get to achieve our goal. The problem is that a file name is not a legal cpp variable name, If we make it legal using cpp code, the MACRO complains, after the MACRO substitution, it is not valid anymore, see the comment in the code

So, is there any way to solve the dilemma, or is there another way to get a dynamically named variable?

In addition, we use CMake in our project, not sure if CMAKE can help, any solutions related to CMAKE are also highly appreciated


Solution

  • You can't, fundamentally.

    Macros are handled by the C++ preprocessor. It works on tokens. It can turn a token into a string (FOO => "FOO") but it can't turn a string back into a token. __FILE__ is a string, as you discovered, while a variable name has to be an unquoted token.

    getFileNameAsVarName is a C++ function, and even consteval functions run after the preprocessor has completely finished. At that time, all tokens are final.