Какое условие препроцессора я должен проверить, чтобы использовать __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]]
Если это не разумное решение, я подозреваю, что вам, к сожалению, придется проверять конкретные компиляторы и версии в этом условии.