Условная компиляция на основе строки, переданной в макросе - PullRequest
0 голосов
/ 06 ноября 2019

У меня есть макрос вида:

#define SAMPLE_MACRO(x) somefunction(x)

Я вызываю макрос со строками в качестве параметра:

SAMPLE_MACRO("abc");
SAMPLE_MACRO("bbe");
SAMPLE_MACRO("ccb");
SAMPLE_MACRO("axx");

Можно ли заставить препроцессор анализировать строку так, чтобыесли допустим, что он начинается с «a» (поэтому строки «abc» и «axx» в приведенном выше примере) макрос будет вызывать какую-то другую функцию, а не somefunction ()? Другими словами, я не хочу добавлять оператор «if» внутри макроса, который выполняется во время выполнения и сравнивает строку, но я хочу, чтобы макрос имел другое поведение в зависимости от строкового параметра, указанного при компиляции. Я предполагаю, что это может включать добавление некоторого #ifdef внутри макроса. Возможно ли это в C ++ 11?

Ответы [ 2 ]

0 голосов
/ 06 ноября 2019

Похоже, вы пытаетесь преждевременно оптимизировать что-то. Если это так, то следует отметить, что вам на самом деле не нужно. Компилятор должен тривиально оптимизировать условный оператор из-за того, что данные постоянны.

Следующие компиляции без каких-либо условных переходов,

#include <iostream>
using namespace std;

#define SAMPLE_MACRO(x) (x[0] == 'a' ? somefunction1(x) : somefunction2(x))

void somefunction1(const char* arg){
    std::cout << "fn1 " << arg << std::endl;
}
void somefunction2(const char* arg){
    std::cout << "fn2 " <<  arg << std::endl;
}

int main() {
    SAMPLE_MACRO("abc");
    SAMPLE_MACRO("def");
    return 0;
}

main:
        sub     rsp, 8
        mov     edi, OFFSET FLAT:.LC2
        call    somefunction1(char const*)
        mov     edi, OFFSET FLAT:.LC3
        call    somefunction2(char const*)
        xor     eax, eax
        add     rsp, 8
        ret

Godbolt Demo

0 голосов
/ 06 ноября 2019

Я так не думаю. Вы можете создать строку из имени параметра, но не можете проанализировать содержимое параметра.

Звучит так, как если бы вы в любом случае создавали разные макросы для каждого условия строки, поэтому проще всего просто использоватьразные имена для каждого условия, например:

#define SAMPLE_MACRO(x) somefunction(x)
#define SAMPLE_MACRO_A(x) otherfunction(x)

Если макрос состоит из нескольких строк, и вы хотите, чтобы отличалась только одна строка, один из способов - передать имя функции в качестве параметра макроса:

#define SAMPLE_MACRO(f, x) { \
    ...
    f(x);
    ...
}

Позвоните куда-нибудь:

SAMPLE_MACRO(otherfunction, "abc");
SAMPLE_MACRO(somefunction, "bbe");

Другой вариант - создать макросы для других строк и использовать их в определенных макросах:

#define SAMPLE_MACRO_PRE(x) ...
#define SAMPLE_MACRO_POST(x) ...

#define SAMPEL_MACRO(x) { \
    SAMPLE_MACRO_PRE(X); \
    somefunction(x); \
    SAMPLE_MACRO_POST(x); \
}
#define SAMPEL_MACRO_A(x) { \
    SAMPLE_MACRO_PRE(X); \
    otherfunction(x); \
    SAMPLE_MACRO_POST(x); \
}

Thisэто все, что относится и к Си. Если вы хотите быть объектно-ориентированным, подумайте о создании классов для обработки различий в строках, а не в макросах. Наследовать от базового типа и иметь разные реализации функции-члена .somefunction (). Правильная ориентация объекта может устранить множество операторов switch () или каскадных операторов if ().

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