#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;
}
Это может выглядеть зашитым, но у нас есть действительный вариант использования. Наше намерение состоит в том, чтобы объявить переменную с динамическим именем, т. е. имя переменной определяется именем файла и строкой. Нет. Мы пытаемся добиться этого с помощью макроса, похоже, это единственный шанс, который мы получаем для достижения нашей цели. Проблема в том, что имя файла не является допустимым именем переменной cpp. Если мы сделаем его допустимым с помощью кода cpp, MACRO жалуется, после замены MACRO оно больше не действительно, см. комментарий в коде.
Итак, есть ли способ решить эту дилемму или есть другой способ получить переменную с динамическим именем?
Кроме того, мы используем CMake в нашем проекте, не уверен, что CMAKE может помочь, любые решения, связанные с CMAKE, также высоко ценятся.
declare a dynamically named variable
Невозможно. Если вы хотите динамически определять имена переменных, рассмотрите Python или Bash, язык сценариев. Обычно вы объединяете статическое имя с номером строки, например XCONCAT(aaa, __LINE__)
.
В целом, это похоже на вопрос XY. Какой смысл определять такую переменную, если у вас никогда не будет возможности сослаться на нее? Какую реальную проблему вы пытаетесь решить?
Re: if (c > 'a' && c < 'z')
-- это не гарантированно сработает. Используйте std::islower или, чтобы включить как строчные, так и прописные буквы, std::isalpha.
@NathanOliver Я задал вопрос от имени моего коллеги, я перезвоню тебе позже. Кажется, такой трюк используется проектом с открытым исходным кодом. Он следует за ним. Любой другой способ достижения той же цели определенно приветствуется.
@PeteBecker Хотя это не имеет значения... просто демо. Вопрос в том, как правильно использовать макрос.
Если вы хотите динамически добавлять имя, связанное с переменной, вам может понадобиться std::map<std::string,sometype>
или std::hash_map<std::string,sometype>
, где строка является именем.
@KamilCuk Я свяжусь с тобой позже, после того как спрошу своего коллегу. Кажется, это связано с каким-то указателем на динамическую функцию. К тому времени я укажу на репозиторий с открытым исходным кодом.
@drescherjm Я тоже в это верю. Я укажу вам репозиторий с открытым исходным кодом после того, как завтра доберусь до своего коллеги.
При компиляции используйте -DFILE_TOKEN=main_cpp
, а затем FILE_TOKEN
, чтобы имя файла было объединено с номером строки.
«у нас есть действительный вариант использования». Этой информации недостаточно, чтобы спросить нас, как удовлетворить ваш вариант использования. Пожалуйста, опишите реальную проблему, которую вы пытаетесь решить, а не просите нас исправить загадочную проблему.
Почему вы хотите это сделать? («Наше намерение состоит в том, чтобы объявить переменную с динамическим именем» — это недопустимый вариант использования, это предлагаемое вами решение для любого фактического варианта использования.) Почему имя переменной имеет значение? В любом случае имя не существует во время выполнения.
Вы не можете, в принципе.
Макросы обрабатываются препроцессором C++. Это работает на токенах. Он может превратить токен в строку (FOO => «FOO»), но не может превратить строку обратно в токен. Как вы обнаружили, __FILE__
— это строка, а имя переменной должно быть токеном без кавычек.
getFileNameAsVarName
— это функция C++, и даже функции consteval
запускаются после полного завершения работы препроцессора. На данный момент все токены являются окончательными.
При компиляции используйте
-DFILE_TOKEN=main_cpp
, а затемFILE_TOKEN
, чтобы имя файла было объединено с номером строки.
–
Элджей (ссылка)
И указанное выше имя файла может быть сгенерировано автоматически командной оболочкой. Большая часть этого обсуждается здесь: stackoverflow.com/questions/8487986/file-macro-shows-full-path
Можем ли мы увидеть вариант использования? Как бы вы могли вернуться к переменной?