Поиск…
Синтаксис
[[details]]: простой атрибут без аргумента
[[details (аргументы)]]: Атрибут с аргументами
__attribute (подробности): нестандартная спецификация GCC / Clang / IBM
__declspec (подробности): нестандартная спецификация MSVC
[[без возврата]]
В C ++ 11 был введен атрибут [[noreturn]]
. Он может использоваться для функции, указывающей на то, что функция не возвращается к вызывающей стороне, либо выполняя оператор return , либо достигая конца, если это тело (важно отметить, что это не относится к функциям void
, поскольку они возвращайтесь к вызывающему, они просто не возвращают никакого значения). Такая функция может завершиться вызовом std::terminate
или std::exit
или путем исключения исключения. Также стоит отметить, что такая функция может вернуться, выполнив longjmp
.
Например, функция, приведенная ниже, всегда будет либо выдавать исключение, либо вызывать std::terminate
, поэтому он является хорошим кандидатом для [[noreturn]]
:
[[noreturn]] void ownAssertFailureHandler(std::string message) {
std::cerr << message << std::endl;
if (THROW_EXCEPTION_ON_ASSERT)
throw AssertException(std::move(message));
std::terminate();
}
Такая функциональность позволяет компилятору завершить работу без оператора return, если он знает, что код никогда не будет выполнен. Здесь, поскольку вызов ownAssertFailureHandler
(определенный выше) в приведенном ниже коде никогда не вернется, компилятору не нужно добавлять код ниже этого вызова:
std::vector<int> createSequence(int end) {
if (end > 0) {
std::vector<int> sequence;
sequence.reserve(end+1);
for (int i = 0; i <= end; ++i)
sequence.push_back(i);
return sequence;
}
ownAssertFailureHandler("Negative number passed to createSequence()"s);
// return std::vector<int>{}; //< Not needed because of [[noreturn]]
}
Это неопределенное поведение, если функция действительно вернется, поэтому следующее недопустимо:
[[noreturn]] void assertPositive(int number) {
if (number >= 0)
return;
else
ownAssertFailureHandler("Positive number expected"s); //< [[noreturn]]
}
Обратите внимание, что [[noreturn]]
в основном используется в void-функциях. Однако это не является обязательным требованием, позволяющим использовать функции в общем программировании:
template<class InconsistencyHandler>
double fortyTwoDivideBy(int i) {
if (i == 0)
i = InconsistencyHandler::correct(i);
return 42. / i;
}
struct InconsistencyThrower {
static [[noreturn]] int correct(int i) { ownAssertFailureHandler("Unknown inconsistency"s); }
}
struct InconsistencyChangeToOne {
static int correct(int i) { return 1; }
}
double fortyTwo = fortyTwoDivideBy<InconsistencyChangeToOne>(0);
double unreachable = fortyTwoDivideBy<InconsistencyThrower>(0);
Следующие стандартные функции библиотеки имеют этот атрибут:
- станд :: прерывани
- станд :: Выход
- станд :: quick_exit
- станд :: неожиданный
- станд :: прекратить
- станд :: rethrow_exception
- станд :: throw_with_nested
- станд :: nested_exception :: rethrow_nested
[[провалиться]]
Всякий раз, когда case
заканчивается в switch
, код следующего случая будет выполнен. Последнюю можно предотвратить, используя оператор'break`. Так как это так называемое пошаговое поведение может вводить ошибки, когда они не предназначены, некоторые компиляторы и статические анализаторы дают предупреждение об этом.
Начиная с C ++ 17, был введен стандартный атрибут, указывающий на то, что предупреждение не требуется, когда код должен провалиться. Компиляторы могут безопасно давать предупреждения, когда дело заканчивается без break
или [[fallthrough]]
и имеет хотя бы одно заявление.
switch(input) {
case 2011:
case 2014:
case 2017:
std::cout << "Using modern C++" << std::endl;
[[fallthrough]]; // > No warning
case 1998:
case 2003:
standard = input;
}
См. Предложение для более подробных примеров того, как можно использовать [[fallthrough]]
.
[[устаревшие]] и [[устаревшие («причина»)]]
C ++ 14 представил стандартный способ устаревания функций через атрибуты. [[deprecated]]
может использоваться, чтобы указать, что функция устарела. [[deprecated("reason")]]
позволяет добавить определенную причину, которая может быть показана компилятором.
void function(std::unique_ptr<A> &&a);
// Provides specific message which helps other programmers fixing there code
[[deprecated("Use the variant with unique_ptr instead, this function will be removed in the next release")]]
void function(std::auto_ptr<A> a);
// No message, will result in generic warning if called.
[[deprecated]]
void function(A *a);
Этот атрибут может применяться к:
- объявление класса
- typedef-name
- Переменная
- нестатический элемент данных
- функция
- перечисление
- типовая специализация
(см. c ++ 14 стандартная черновик : 7.6.5 Устаревший атрибут)
[[Nodiscard]]
[[nodiscard]]
может использоваться для указания того, что возвращаемое значение функции не должно игнорироваться при вызове функции. Если возвращаемое значение игнорируется, компилятор должен дать предупреждение об этом. Атрибут может быть добавлен в:
- Определение функции
- Тип
Добавление атрибута к типу имеет такое же поведение, как добавление атрибута к каждой отдельной функции, которая возвращает этот тип.
template<typename Function>
[[nodiscard]] Finally<std::decay_t<Function>> onExit(Function &&f);
void f(int &i) {
assert(i == 0); // Just to make comments clear!
++i; // i == 1
auto exit1 = onExit([&i]{ --i; }); // Reduce by 1 on exiting f()
++i; // i == 2
onExit([&i]{ --i; }); // BUG: Reducing by 1 directly
// Compiler warning expected
std::cout << i << std::end; // Expected: 2, Real: 1
}
См. Предложение для более подробных примеров того, как можно использовать [[nodiscard]]
.
Примечание: Детали реализации Finally
/ onExit
опущены в этом примере, см Finally / ScopeExit .
[[Maybe_unused]]
[[maybe_unused]]
создан для указания в коде, что некоторая логика может не использоваться. Это часто связано с условиями препроцессора, где это может быть использовано или может не использоваться. Поскольку компиляторы могут давать предупреждения о неиспользуемых переменных, это способ подавить их, указав намерение.
Типичным примером переменных, которые необходимы в отладочных сборках, в то время как ненужные в производстве, являются возвращаемыми значениями, указывающими успех. В отладочных сборках условие должно быть подтверждено, хотя в производстве эти утверждения были удалены.
[[maybe_unused]] auto mapInsertResult = configuration.emplace("LicenseInfo", stringifiedLicenseInfo);
assert(mapInsertResult.second); // We only get called during startup, so we can't be in the map
Более сложным примером являются различные вспомогательные функции, которые находятся в неназванном пространстве имен. Если эти функции не используются во время компиляции, компилятор может дать предупреждение о них. В идеале вы хотели бы охранять их с теми же тегами препроцессора, что и вызывающий, хотя, поскольку это может стать сложным, атрибут [[maybe_unused]]
является более [[maybe_unused]]
альтернативой.
namespace {
[[maybe_unused]] std::string createWindowsConfigFilePath(const std::string &relativePath);
// TODO: Reuse this on BSD, MAC ...
[[maybe_unused]] std::string createLinuxConfigFilePath(const std::string &relativePath);
}
std::string createConfigFilePath(const std::string &relativePath) {
#if OS == "WINDOWS"
return createWindowsConfigFilePath(relativePath);
#elif OS == "LINUX"
return createLinuxConfigFilePath(relativePath);
#else
#error "OS is not yet supported"
#endif
}
См. Предложение для более подробных примеров того, как [[maybe_unused]]
можно использовать.