2013-04-25 2 views
4

У меня проблема: я хотел бы использовать функцию abs библиотеки complex.Использование функции конкретной библиотеки

Однако, у меня есть ошибка, предупреждающая меня, что функция abs используется #define abs(x) (x > 0) ? x : -(x).

Таким образом, я думаю, что проблема исходит из моего импорта. Из-за того, что я также включаю библиотеки stdio и stdlib, компилятор может использовать функцию abs, определенную в одной из этих библиотек.

Так что мой вопрос: как я могу использовать функцию abs из библиотеки complex без каких-либо импортных данных?

Большое спасибо за ваш ответ.

+0

Имеет ли библиотека 'complex' пространство имен? – juanchopanza

+0

Да, пространство имен является std. Я использую libray «complex» стандартного C99 – user2194381

+1

'std' - это пространство имен C++. – juanchopanza

ответ

15

Обернуть парс вокруг него.

(abs)(whatever); 

Это заставит компилятор использовать версию функции, поскольку макрос больше не совпадает.

Функциональные макросы работают путем сопоставления идентификатора, за которым следует левый парень (. Поскольку мы обернули имя функции в parens, вместо этого вместо этого будет идентификатор, за которым следует правый параграф ), который не соответствует макросу. Parens являются семантически прозрачными, но они препятствуют синтаксису макроса.

IIRC, это был splint контролер C, который преподавал это мне. При написании интерпретатора постскрипта я создал красивые короткие макросы для доступа к стеку.

#define push(o) (*tos++ = (o)) 
#define pop() (*--tos) 

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


Edit: У меня есть мучительное чувство, что это было на самом деле книга Coelocanthe (Deep Secrets Питер Ван дер Линден C), где я узнал об этом, вышеописанной ситуации бытия, где я первый нужно его , IIRC в его примере участвовали putchar или getchar, которые часто реализуются как обе функции, так и макросы в соответствии с реализациями C.

+0

Отлично! Оно работает. Можете ли вы объяснить мне, почему скобки вынуждают компилятор использовать правильное определение? – user2194381

+3

Функциональный вызов макроса состоит из имени макроса, за которым следует открытая скобка. Когда компилятор видит 'abs)', он не может быть вызовом функционально-подобного макроса, потому что символы после имени не являются открытыми скобками. –

+0

Это действительно умный трюк! +1 – Agentlien

6

Использование #undef

#include "header1.h" 
#include "header2.h" 
#undef abs // remove abs macro 

x = std::abs(y); 
1

Оба #undef и круглые скобки решения будут работать, но я бы посоветовал что-то немного сильнее, потому что оба эти решения будут необходимы вам, чтобы сделать их каждый раз, когда вы хотите позвонить abs и рядом время, которое вы можете забыть и привести к ошибке.

, что вы можете сделать:

  1. изменить имя вашей функции менее общее название: absolute, myAbs и т.д. ...
  2. поставить вас функцию \ класс под именем пространства (для C++ не C), то звонки явно myNameSpace::abs(x)
  3. Если он не будет работать, как комментарий здесь предложил я бы еще деформировать вызов в моей функции:

    тип myAbs (тип param) { возвращение (abs) (param); }

+2

Пространство имен не победит макроподстановку. –

+2

Я не уверен, что есть какая-либо «ваша функция», по крайней мере, OP не упоминает об этом. – juanchopanza

4

Хотя несколько предложений выше очень хорошо, я бы совершенно другой угол. Это почти наверняка что-то вроде windows.h, которое вызывает «плохое» определение макроса abs(). Вы должны иметь возможность НЕ включать «windows.h» в файл, который выполняет сложную математику [по крайней мере в большинстве типов программ] (я не знаю ни одной функции в Windows, которая принимает complex<T> в качестве аргумента, поэтому Я уверен, что вам не нужны оба «complex.h» и «windows.h» в том же исходном файле. Этот метод называется «изолирование системных зависимостей», и это очень хорошо.

Посмотрите на свой код и найдите, где вы ACTUALLY, используя функции windows, а затем включите только «windows.h» в файлы, которые на самом деле нуждаются в нем. Вероятно, вы обнаружите, что если вы используете Visual Studio, это «windows.h» включен как часть «stdafx.h», что означает, что всевозможные интересные макросы и т. д. включаются повсеместно, потому что «stdafx.h» включен в ВСЕ исходные файлы.

+0

+1, этого макроса 'abs' следует избегать. Это единственное реальное решение. – juanchopanza

Смежные вопросы