Поиск…


Синтаксис

  • [[details]]: простой атрибут без аргумента

  • [[details (аргументы)]]: Атрибут с аргументами

  • __attribute (подробности): нестандартная спецификация GCC / Clang / IBM

  • __declspec (подробности): нестандартная спецификация MSVC

[[без возврата]]

C ++ 11

В 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

[[провалиться]]

C ++ 17

Всякий раз, когда 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

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]]

C ++ 17

[[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]] можно использовать.



Modified text is an extract of the original Stack Overflow Documentation
Лицензировано согласно CC BY-SA 3.0
Не связан с Stack Overflow