Какое условие препроцессора я должен проверить, чтобы использовать __attribute__((const))?

У меня есть фрагмент кода, который применяется __attribute__((const))к некоторым функциям. Я бы предпочел не удалять его, когда он пригоден для использования, но, с другой стороны, я действительно хочу быть более портативным, поэтому - я хочу сказать

#if some condition here
#define ATTRIBUTE(an_attribute)  __attribute__((an_attribute))
#else
#define ATTRIBUTE(an_attribute)  
#endif

void foo(int x) ATTRIBUTE(const)

Какое должно быть состояние?

Заметки:

  • Я знаю, что в C++17 это правильный атрибут C++; но я не могу предположить, что используется C++17. На самом деле, давайте предположим, что это не для упрощения.
  • Дополнительные баллы, если вы также можете ответить на вопрос для __attribute__((pure)).

2 ответа

Решение

__attribute__это расширение GNU. Только компиляторы GNU и компиляторы, претендующие на звание GNU (такие как Clang и ICC), поддерживают его. Итак, вы можете сделать это:

#ifdef __GNUC__
# define ATTRIBUTE(x) __attribute__ (x)
# else
# define ATTRIBUTE(x)
#endif

const был представлен в GCC 2.5, и pureво время разработки GCC 2.96, поэтому нет смысла тестировать их поддержку отдельно: эти версии компилятора все равно не смогут компилировать текущий код C++. (__attribute__сам был представлен в GCC 2.0. Я думаю, что интерфейс C++ всегда его поддерживал.)

GCC предоставляет эти атрибуты в соответствии со стандартным синтаксисом атрибутов, представленным в C++11:

[[gnu::const]] // or [[gnu::pure]]
void foo(int x);

Начиная с C++17, компиляторы должны игнорировать неизвестные атрибуты, не вызывая ошибки. На практике компиляторы часто предупреждают о неизвестных атрибутах (конечно, с возможностью отключения этого предупреждения). Из того, что я видел в Compiler Explorer, и из того, что я помню, компиляторы старше C++17 также обычно предупреждают, когда они вообще понимают синтаксис. Основной компилятор, который я хотел бы дополнительно протестировать, - это MSVC, но Compiler Explorer не уходит слишком далеко в версии MSVC.

Если у вас уже есть макрос и вы не хотите менять его использование, вы можете работать с ним в:

#define ATTRIBUTE(an_attribute) [[gnu::an_attribute]]

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

Другие вопросы по тегам