Как я заставляю макрос C++ вести себя как функция?

При обновлении до Xcode 7.1 вы можете увидеть этот тип ошибки, и он не может быть разрешен ни одним из приведенных выше ответов. Одним из симптомов в моем случае было то, что приложение работает на устройстве не в симуляторе. Вероятно, вы увидите огромное количество ошибок, связанных со значительной частью всех используемых вами фреймворков.

Исправление на самом деле довольно простое. Вам просто нужно удалить запись из параметра «Пути поиска в Ракурсе», найденного в разделе TARGETS> Build Settings> Search Paths (убедитесь, что выбрана вкладка «Все»)

Если вы видите другую запись (помимо $ (унаследованной)) для своей основной цели или вашей целевой цели, просто удалите неисправный путь из всех целей и перестройте.

48
задан 8 revs, 4 users 74% 23 May 2017 в 02:18
поделиться

7 ответов

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

, Если это должен быть макрос, некоторое время цикл (уже предложенный) будет работать, или можно попробовать оператор запятой:

#define MACRO(X,Y) \
 ( \
  (cout << "1st arg is:" << (X) << endl), \
  (cout << "2nd arg is:" << (Y) << endl), \
  (cout << "3rd arg is:" << ((X) + (Y)) << endl), \
  (void)0 \
 )

(void)0 причины оператор для оценки к одному из void тип и использование запятых, а не точек с запятой позволяют ему использоваться в операторе, а не только как автономное. Я все еще рекомендовал бы подставляемую функцию для хоста причин, наименьшее количество которых, будучи объемом и тем, которое MACRO(a++, b++) увеличит a и b дважды.

42
ответ дан coppro 7 November 2019 в 12:12
поделиться

Существует довольно умное решение:

#define MACRO(X,Y)                         \
do {                                       \
  cout << "1st arg is:" << (X) << endl;    \
  cout << "2nd arg is:" << (Y) << endl;    \
  cout << "Sum is:" << ((X)+(Y)) << endl;  \
} while (0)

Теперь у Вас есть единственный оператор блочного уровня, который должен сопровождаться точкой с запятой. Это ведет себя как ожидалось и желаемый во всех трех примерах.

43
ответ дан Kip 7 November 2019 в 12:12
поделиться

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

Самый Близкий я знаю о:

#define MACRO(X,Y) \
do { \
    auto MACRO_tmp_1 = (X); \
    auto MACRO_tmp_2 = (Y); \
    using std::cout; \
    using std::endl; \
    cout << "1st arg is:" << (MACRO_tmp_1) << endl;    \
    cout << "2nd arg is:" << (MACRO_tmp_2) << endl;    \
    cout << "Sum is:" << (MACRO_tmp_1 + MACRO_tmp_2) << endl; \
} while(0)

Это делает следующее:

  • Работы правильно в каждом из установленных контекстов.
  • Оценивает каждый из его аргументов точно однажды, который является гарантируемой функцией вызова функции (принимающий в обоих случаях исключения в любом из тех выражений).
  • законы на любых типах, при помощи "автоматического" от C++ 0x. Это еще не стандартный C++, но нет никакого другого способа требовать tmp переменных по правилу единственной оценки.
  • не требует, чтобы вызывающая сторона импортировала имена из станд. пространства имен, который делает исходный макрос, но функция не была бы.

Однако это все еще отличается от функции в этом:

  • В некотором недопустимом использовании это может дать различные ошибки компилятора или предупреждения.
  • Это идет не так, как надо, если X или Y содержат использование 'MACRO_tmp_1' или 'MACRO_tmp_2' от окружающего объема.
  • Связанный с вещью станд. пространства имен: функция использует свой собственный лексический контекст для поиска имен, тогда как макрос использует контекст своего сайта вызова. Нет никакого способа записать макрос, который ведет себя как функция в этом отношении.
  • Это не может использоваться в качестве выражения возврата пустой функции, которая может пустое выражение (такое как решение для запятой). Это - еще больше проблемы, когда желаемый тип возврата не является пустым, особенно, когда используется в качестве lvalue. Но решение для запятой не может включать объявления использования, потому что они - операторы, так выберите один или используйте ({...}) Расширение GNU.
18
ответ дан IAbstract 7 November 2019 в 12:12
поделиться

Создайте блок с помощью

 #define MACRO(...) do { ... } while(false)

, не добавляют a; после, в то время как (ложь)

4
ответ дан Andrew Stein 7 November 2019 в 12:12
поделиться

Ваш ответ страдает от проблемы нескольких-оценок, таким образом (например),

macro( read_int(file1), read_int(file2) );

сделает что-то неожиданное и вероятно нежелательный.

3
ответ дан 7 November 2019 в 12:12
поделиться

Как другие упомянули, необходимо избежать макросов, когда это возможно. Они опасны в присутствии побочных эффектов, если макро-аргументы оценены несколько раз. Если Вы знаете тип аргументов (или может использовать функцию 0x auto C++), Вы могли использовать временные файлы для осуществления единственной оценки.

Другая проблема: порядок, в котором происходят несколько оценок, не может быть тем, что Вы ожидаете!

Рассматривают этот код:

#include <iostream>
using namespace std;

int foo( int & i ) { return i *= 10; }
int bar( int & i ) { return i *= 100; }

#define BADMACRO( X, Y ) do { \
    cout << "X=" << (X) << ", Y=" << (Y) << ", X+Y=" << ((X)+(Y)) << endl; \
    } while (0)

#define MACRO( X, Y ) do { \
    int x = X; int y = Y; \
    cout << "X=" << x << ", Y=" << y << ", X+Y=" << ( x + y ) << endl; \
    } while (0)

int main() {
    int a = 1; int b = 1;
    BADMACRO( foo(a), bar(b) );
    a = 1; b = 1;
    MACRO( foo(a), bar(b) );
    return 0;
}

И это производится, как скомпилировано и работается моя машина:

X=100, Y=10000, X+Y=110
X=10, Y=100, X+Y=110
1
ответ дан jwfearn 7 November 2019 в 12:12
поделиться

Если Вы готовы принять практику всегда использования фигурных скобок в Вашем, если бы операторы,

Ваш макрос просто пропустил бы последнюю точку с запятой:

#define MACRO(X,Y)                       \
cout << "1st arg is:" << (X) << endl;    \
cout << "2nd arg is:" << (Y) << endl;    \
cout << "Sum is:" << ((X)+(Y)) << endl

Пример 1: (компиляции)

if (x > y) {
    MACRO(x, y);
}
do_something();

Пример 2: (компиляции)

if (x > y) {
    MACRO(x, y);
} else {
    MACRO(y - x, x - y);
}

Пример 3: (не компилирует)

do_something();
MACRO(x, y)
do_something();
-2
ответ дан Ates Goral 7 November 2019 в 12:12
поделиться
Другие вопросы по тегам:

Похожие вопросы: