Как передать строковый аргумент в макрос - PullRequest
0 голосов
/ 13 марта 2020

Я пытаюсь напечатать IT SUCCESS\nET SUCCESS\n, используя следующий код, но он не скомпилируется с ошибкой error: ‘printds’ was not declared in this scope, которую я знаю, потому что он принимает макро-ввод как ds литерал. Кто-нибудь знает как это сделать? Сценарий использования состоит в том, что есть несколько функций printXX (), которые должны вызываться на основе значения, переданного в макросе.

#include <stdio.h>
#define FOO(val) { \
    print ## val();    \
}
void printIT() { printf("IT SUCCESS\n"); }
void printET() { printf("ET SUCCESS\n"); }

int main() {
    const char* ds = "IT", es = "ET";
    FOO(ds); FOO(es);
    return 0;
}

Ответы [ 4 ]

2 голосов
/ 13 марта 2020

Вы можете изменить

 FOO(ds); FOO(es);

на

 FOO(IT); FOO(ET);

Поскольку замены макросов происходят до того, как ваш код скомпилирован.

Но вы можете определить функцию с именем FOO, например

#include <stdio.h>
#include <iostream>

using namespace std;

void printIT() { printf("IT SUCCESS\n"); }
void printET() { printf("ET SUCCESS\n"); }

void FOO(const string str)
{
    if(str=="IT")
        printIT();
    else
        printET();
}

int main()
{
    const char* ds = "IT",*es="ET";
    FOO(ds);FOO(es);
    return 0;
}
1 голос
/ 13 марта 2020

принимает макро-ввод как ds литерал.

Да, этого и следовало ожидать. Макросы препроцессора раскрываются во время компиляции. Аргументами для функционально-подобных макросов являются буквальные токены исходного кода, которые появляются в скобках при вызове макроса. Они не имеют никакого дополнительного значения для препроцессора.

Кто-нибудь знает, как это сделать? Случай использования состоит в том, что есть несколько функций printXX (), которые должны вызываться на основе значения, переданного в макросе.

Опять же, макросы расширяются до исходного кода (приблизительно) во время компиляции. Процесс не учитывает и не может принимать во внимание семантику времени выполнения C ++, такую ​​как преобразование идентификаторов переменных в соответствующие значения.

Если динамическая диспетчеризация c во время выполнения - это то, что вам нужно, тогда вам нужно совершенно другой механизм. Например, вы можете использовать обычные условные операторы для выбора между различными вызовами функций. Если вы хотите быть еще более динамичным c, вы можете подготовить таблицу поиска указателей функций и использовать ее для выбора и вызова соответствующих функций.

В комментариях вы добавили

У меня есть несколько методов queryServers, queryNodes, queryTargets, которые я хочу вызвать, используя описанный выше трюк.

Возможно, вы сможете sh выполнить нечто похожее на то, что Вы спрашиваете через шаблоны или перегруженные функции. Эти механизмы также работают во время компиляции, поэтому у них нет доступа к информации времени выполнения, такой как значения переменных, но они знают о типах данных C ++ и полагаются на них.

В качестве альтернативы, возможно, вы ищете Шаблон стратегии .

0 голосов
/ 13 марта 2020

Возможное решение без MACRO:

void printIT() { printf("IT SUCCESS\n"); }
void printET() { printf("ET SUCCESS\n"); }

void foo(std::string_view s)
{
    static const std::map<std::string_view, void(*)()> funcs{
        {"IT", &printIT},
        {"ET", &printET}
    };

    auto it = funcs.find(s);
    if (it != funcs.end()) {
        (*it->second)();
    }
}

int main() {
    const char* ds = "IT";
    const char* es = "ET";
    foo(ds); foo(es);
}

Демо

0 голосов
/ 13 марта 2020

Первое, что вам нужно знать, это то, что макросы - это директивы препроцессора, представляющие собой фрагмент кода с заданным именем. если вы используете имя макроса в своей программе, он заменит этот фрагмент кода в том месте, где вы используете имя макроса во время первого этапа компиляции, называемого этапом предварительной обработки.

#include <stdio.h>
#define FOO(val) { \
    print ## val();    \
}
void printIT() { printf("IT SUCCESS\n"); }
void printET() { printf("ET SUCCESS\n"); }

int main() {
    const char* ds = "IT", es = "ET";
    FOO(ds); FOO(es);
    return 0;
}

В своем коде вы пытаетесь вводить переменные ds и es в функцию FOO, как макрос. Но переменные ds и es объявляются в программном стеке только при запуске программы. Во время компиляции он просто обрабатывает их как только тексты. Поэтому для ввода макрос-функции он принимает текст ds и es и заменяется на val. Вот почему вы получили ошибку времени компиляции. Следующий фрагмент кода, который я изменил, работает, как вы и ожидали.

#include <stdio.h>
#define FOO(val) { \
    print ## val();    \
}
void printIT() { printf("IT SUCCESS\n"); }
void printET() { printf("ET SUCCESS\n"); }

int main() {
    const char* ds = "IT", *es = "ET";
    FOO(IT); FOO(ET);
    return 0;
}

Если вам интересно, вы можете узнать больше о макросах в следующих ресурсах. G CC электронная документация и Статья о макросах . Также вы можете просмотреть предварительно обработанный код, используя g++ -E (your cpp file name). Спасибо.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...