Получить возвращаемый тип функции в макросе (C ++) - PullRequest
2 голосов
/ 29 декабря 2011

У меня есть макрос ASSERT(x), и я хочу вызвать return, если он утверждает (в конфигурации выпуска). Для этого мне нужно знать тип возвращаемого значения функции, где я использую это ASSERT. Как его получить (я имею дело с C++03, LLVM GCC 4.2 компилятором)?

Мой макрос ASSERT:

#define ASSERT(x) \
    if(!(x)) {
        LOG ("ASSERT in %s: %d", __FILE__, __LINE__); \
        return /*return_type()*/; \
    }

PS: я пытался return 0; - компилятор показывает ошибку для пустых функций (и я не пробовал это для сложных возвращаемых типов), если return; - ошибка для не пустых функций.

(обновление ...)

Я отвечу Оборотень , Ньярлатхотеп и JDV-Ян де Ваан здесь. Я использую стандарт assert для конфигурации отладки. Но после бета-тестирования я все еще получаю отчеты о сбоях от конечных клиентов, и в большинстве случаев мне нужно изменить свои функции сбоя:

ASSERT (_some_condition_);
if (!_some_condition_)      // add this return
    return _default_value_;

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

Ответы [ 6 ]

4 голосов
/ 29 декабря 2011

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

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

2 голосов
/ 29 декабря 2011

Нет правильного способа определить тип возврата внутри функции в C.

Кроме того, если вы каким-либо образом реализуете свой вариант ASSERT, это приведет к ошибочному поведению программы.Основная идея ASSERT: в случае сбоя программа находится в неопределенном состоянии, и единственный правильный способ - остановить ее сейчас.Т.е. по телефону exit().

1 голос
/ 29 декабря 2011

Вы не можете этого сделать, препроцессор C / C ++ довольно прост и не может выполнять какой-либо анализ кода.Самое большее, что вы можете сделать, это передать тип возвращаемого значения макросу.

Но вот мое мнение: вы используете утверждения неверным образом.Они должны использоваться только для проверки работоспособности кода (для ошибок, которые могут произойти только из-за программиста);если все утверждения пройдены, вам не нужно заботиться о них, вам не нужно регистрировать их.

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

0 голосов
/ 29 декабря 2011

Вы можете просто определить другой макрос для ваших нужд.

#define ASSERT(x) \
    if(!(x)) { \
        LOG ("ASSERT in %s: %d", __FILE__, __LINE__); \
        ASSERT_DEFAULT_RETURN(); \
    }

А потом внутри функции:

int foo(){
#ifdef ASSERT_DEFAULT_RETURN
#undef ASSERT_DEFAULT_RETURN
#endif
#define ASSERT_DEFAULT_RETURN() return 0
  // ...
  ASSERT(some_expression);
  // ...
  // cleanup
#undef ASSERT_DEFAULT_RETURN
}
0 голосов
/ 29 декабря 2011

Я думаю, вы можете сделать это с помощью функции шаблона, которую вы вызываете default (x) из макроса.

template<class T> default<T>(T x) { return T(); }

, который будет работать для каждого с конструктором по умолчанию. Я думаю, вам нужно написать специальный макрос для void.

Надеюсь, я правильно понял синтаксис шаблона, мой c ++ стал ржавым.

0 голосов
/ 29 декабря 2011

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

Нет способа получить return value из макроса.

...