Как я могу макрос #define статический вызов метода в C ++? - PullRequest
1 голос
/ 18 апреля 2019

Я пытаюсь написать программное обеспечение, которое может вести себя по-разному в зависимости от того, должен ли определенный компонент моделироваться в программном обеспечении или выполняться на реальном оборудовании.Однако GCC жалуется, что оператор разрешения области (: :) не может использоваться в макросе, поэтому мой вопрос: возможно ли определить макрос для вызова статического метода?

Моя цель - уметьчтобы, используя другое определение препроцессора, выбрать между использованием всех реальных компонентов (0), использованием всех смоделированных компонентов (1) или использованием комбинации реальных и смоделированных компонентов (2).В этом последнем случае я сталкиваюсь с этой проблемой.В этом случае я хочу вызвать функцию, которую я «защищаю», реализовав ее как статический метод.Вот мой подход:

#define SIM_CONF 2

#if SIM_CONF == 0
#define IS_HW_SIMULATED(name) false
#define IS_HW_REAL(name) true
#endif

#if SIM_CONF == 1
#define IS_HW_SIMULATED(name) true
#define IS_HW_REAL(name) false
#endif

#if SIM_CONF == 2
#define IS_HW_SIMULATED(name) SimConfig::isSimulated(name)
#define IS_HW_REAL(name) SimConfig::isReal(name)
#endif

class SimConfig
{
public:

    static bool isSimulated(const char* szName);
    static bool isReal(const char* szName);
};

РЕДАКТИРОВАТЬ: Вот пример того, как я использую его в другом месте:

void PumpComponent::commandRevs(float revs)
{
#if IS_HW_SIMULATED("PumpComponent")
    // do simulation procedure
#else
    // do real hardware procedure
#endif
}

Когда я компилирую, GNU Make жалуется:

error: token "::" is not valid in preprocessor expressions
#define IS_HW_SIMULATED(name) SimConfig::isSimulated(name)

Есть ли какой-нибудь подход, в котором я могу защитить / инкапсулировать функции isSimulated() и isReal() и по-прежнему иметь возможность ссылаться на них в директивах препроцессора?

Ответы [ 2 ]

3 голосов
/ 18 апреля 2019

Проблема в том, как вы используете этот макрос.Вы поместили его в качестве аргумента препроцессора #if.

Процессор не понимает код и аргумент #if должен быть чем-то, что процессор может обрабатывать, поэтому макросы и литералы.

SimConfig::isSimulatedэто код, который еще не определен.Это будет известно во время процесса компиляции, поэтому после завершения предварительной обработки.

Один из способов исправить это просто использовать if else

void PumpComponent::commandRevs(float revs)
{
    if IS_HW_SIMULATED("PumpComponent") {
        // do simulation procedure
    } else {
        // do real hardware procedure
    }
}

Это не проблема для компилятора.он заметит, что это константа и должен удалить устаревший код.

Другой способ исправить это - отказаться от макросов.Вы можете использовать шаблоны.

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

1 голос
/ 18 апреля 2019

Не используйте #if для этого. Просто напишите нормальный код:

void PumpComponent::commandRevs(float revs)
{
    if (IS_HW_SIMULATED("PumpComponent")) {
        // do simulation procedure
    } else {
        // do real hardware procedure
    }
}

Компилятор удалит одну из ветвей, когда SIM_CONF равен 0 или 1, поскольку условие ветвления является константой времени компиляции. Это будет держать ветви, когда это 2.

Однако я не вижу причин, чтобы вообще иметь макросы IS_HW_SIMULATED и IS_HW_REAL. Глядя на код, который вы разместили, кажется, вам нужна только одна функция: SimConfig::isSimulated():

bool SimConfig::isSimulated(const char* szName)
{
#if SIM_CONF == 1
    (void)szName; // supress "unused parameter" warning
    return true;
#else
    // Your normal implementation.
#endif
}

Остальная часть кода не нуждается в использовании макросов:

void PumpComponent::commandRevs(float revs)
{
    if (SimConfig::isSimulated("PumpComponent")) {
        // do simulation procedure
    } else {
        // do real hardware procedure
    }
}

SimConfig::isReal(), похоже, не служит какой-либо цели.

...