Атрибуты в C++ 2/2.
Кроме стандартных атрибутов есть ещё всякие компилятороспецифичные.
Тут стоит сказать, что хотя конечно в целом компиляторы в основном умеют работать с атрибутами со стандартным attribute-specifier (
[[]]), в зависимости от компилятора часто используются формы вроде __attribute__(()), __declspec() или, реже, прагм. По самим атрибутам.
Если вы уверены, что что-то нужно сто процентов заинлайнить, в gcc можно использовать
__attribute__((always_inline)). Он игнорирует все лимиты, по которым решается, инлайнить ли функцию/метод, и игнорирует -fno-inline. Есть вот небольшая преза с бенчмарками по этому атрибуту. Есть и довольно специфические атрибуты. Например в clang атрибут
[[clang::preferred_name(some_name)]] может быть применён к шаблону класса и указывает предпочтительный способ присвоения имени специализации шаблона. Или например
using_if_exists, который позволяет не ругаться на юзинги, если в них используются несуществующие/необъявленные сущности. Таким образом ошибки откладываются до момента использования:namespace empty_namespace {};
__attribute__((using_if_exists))
using empty_namespace::does_not_exist; // no error!
does_not_exist x; // error: use of unresolved 'using_if_exists'Или например
noescape к параметру-указателю говорит, что этот указатель никуда не “убежит”. Т.е. вы его ни во что, что может использоваться дальше, не присвоите (вызвать free можно):int* gp;
void no(__attribute__((noescape)) int* p) {
*p += 100; // OK.
}
void yes(__attribute__((noescape)) int* p) {
gp = p; // Not OK.
}Из полезного ещё есть
__attribute__((weak)) в clang (__attribute_((weak_import)) в gcc). Weak линковка это когда вы можете пометить некоторую реализацию функции подобным атрибутом, но если будет найдена другая без подобного атрибута, ей отдаётся предпочтение. Типичный пример — перегрузка operator new/operator delete. В msvc подобного результата (насколько я знаю) можно достичь с прагмами. Рядышком есть ещё
[[selectany]], которые разрешает компилятору выбрать любую реализацию. Из прекрасного про msvc факт, что
[[no_unique_address]], как уже говорилось, на нём не работает. Нужно юзать специфичный компиляторный. Но это только если у вас msvc. Если хотите под windows собирать с clang’ом, земля вам пухом.И много других:
enable_if (который делает примерно то, что вы и думаете), format (который говорит, что функция принимает printf/scanf-like format строку и аргументы для неё), malloc (говорит, что функция ведёт как функция для выделения памяти из системы, no_sanitize (отключающий проверки санитайзеров для конкретной функции или глобальной переменной), constructor (позволяет выполнить некоторый код до запуска main(), подробнее Женя писал в https://t.me/cxx95/109) и destructor (после выхода из main()), call_once (утверждающий, что параметр-функтор вызывается ровно однажды). Больше атрибутов можно увидеть тут: clang, gcc.