Sök…


Syntax

  • [[detaljer]]: Enkelt attribut utan argument

  • [[detaljer (argumenter)]]: Attribut med argument

  • __attribut (detaljer): Icke-standard GCC / Clang / IBM-specifik

  • __declspec (detaljer): Icke-standard MSVC-specifik

[[ingen återvändo]]

C ++ 11

C ++ 11 introducerade attributet [[noreturn]] . Den kan användas för en funktion för att indikera att funktionen inte återgår till den som ringer genom att antingen utföra en återgång uttalande eller genom att nå slutet om det kropp (det är viktigt att notera att detta inte gäller void funktioner eftersom de kommer tillbaka till den som ringer, de returnerar bara inget värde). En sådan funktion kan avslutas genom att ringa std::terminate eller std::exit , eller genom att kasta ett undantag. Det är också värt att notera att en sådan funktion kan återvända genom att köra longjmp .

Exempelvis kommer funktionen nedan alltid antingen att kasta ett undantag eller ringa std::terminate , så det är en bra kandidat för [[noreturn]] :

[[noreturn]] void ownAssertFailureHandler(std::string message) {
    std::cerr << message << std::endl;
    if (THROW_EXCEPTION_ON_ASSERT)
        throw AssertException(std::move(message));
    std::terminate();
}

Den här typen av funktionalitet gör det möjligt för kompilatorn att avsluta en funktion utan returrätt om den vet att koden aldrig kommer att köras. Eftersom samtalet till ownAssertFailureHandler (definierat ovan) i koden nedan aldrig kommer att återvända, behöver kompilatorn inte lägga till kod under det samtalet:

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

Det är odefinierat beteende om funktionen faktiskt kommer att återvända, så följande är inte tillåtet:

[[noreturn]] void assertPositive(int number) {
    if (number >= 0)
        return;
    else
        ownAssertFailureHandler("Positive number expected"s); //< [[noreturn]]
}

Observera att [[noreturn]] mest används i ogiltiga funktioner. Detta är emellertid inte ett krav, vilket gör att funktionerna kan användas i generisk programmering:

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);

Följande standardbiblioteksfunktioner har detta attribut:

  • std :: abort
  • std :: exit
  • std :: quick_exit
  • std :: oväntad
  • std :: avsluta
  • std :: rethrow_exception
  • std :: throw_with_nested
  • std :: nested_exception :: rethrow_nested

[[falla igenom]]

C ++ 17

Varje gång ett case avslutas i en switch , kommer koden för nästa ärende att köras. Den här sista kan förhindras genom att använda "break" -satsen. Eftersom detta så kallade banbrytande beteende kan införa buggar när det inte är avsett, ger flera kompilatorer och statiska analysatorer en varning om detta.

Från C ++ 17 infördes ett standardattribut för att indikera att varningen inte behövs när koden är tänkt att falla igenom. Compilers kan säkert varna när ett ärende avslutas utan break eller [[fallthrough]] och har minst ett uttalande.

switch(input) {
    case 2011:
    case 2014:
    case 2017:
        std::cout << "Using modern C++" << std::endl;
        [[fallthrough]]; // > No warning
    case 1998:
    case 2003:
        standard = input;
}

Se förslaget för mer detaljerade exempel på hur [[fallthrough]] kan användas.

[[deprecated]] och [[deprecated ("anledningen")]]

C ++ 14

C ++ 14 introducerade ett vanligt sätt att avskriva funktioner via attribut. [[deprecated]] kan användas för att indikera att en funktion avskrivs. [[deprecated("reason")]] gör det möjligt att lägga till en specifik anledning som kan visas av kompilatorn.

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);

Detta attribut kan tillämpas på:

  • en klassdeklaration
  • ett typedef-namn
  • en variabel
  • en icke-statisk datamedlem
  • en funktion
  • en uppräkning
  • en mallspecialisering

(ref. c ++ 14 standardutkast : 7.6.5 Utskrivet attribut)

[[Nodiscard]]

C ++ 17

[[nodiscard]] kan användas för att indikera att returfunktionen för en funktion inte borde ignoreras när du gör ett funktionssamtal. Om returvärdet ignoreras bör kompilatorn varna för detta. Attributet kan läggas till:

  • En funktionsdefinition
  • En typ

Att lägga till attributet till en typ har samma beteende som att lägga till attributet till varje enskild funktion som returnerar denna typ.

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
}

Se förslaget för mer detaljerade exempel på hur [[nodiscard]] kan användas.

Obs! Implementeringsdetaljerna för Finally / onExit utelämnas i exemplet, se slutligen / ScopeExit .

[[Maybe_unused]]

[[maybe_unused]] skapas för att i kod ange att viss logik kanske inte används. Detta om det ofta är kopplat till förbehandlarförhållanden där detta kan användas eller kanske inte kan användas. Eftersom kompilatorer kan ge varningar om oanvända variabler är detta ett sätt att undertrycka dem genom att indikera avsikt.

Ett typiskt exempel på variabler som behövs i felsökning medan de inte behövs i produktionen är returvärden som indikerar framgång. I felsökningsbyggnaderna bör villkoret hävdes, även om produktionen har tagits bort.

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

Ett mer komplicerat exempel är olika typer av hjälpfunktioner som finns i ett namngivet namnområde. Om dessa funktioner inte används under sammanställningen, kan en kompilator varna för dem. Helst vill du skydda dem med samma förbehandlartaggar som den som ringer, men eftersom detta kan bli komplex är att [[maybe_unused]] ett mer underhållbart alternativ.

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
}

Se förslaget för mer detaljerade exempel på hur [[maybe_unused]] kan användas.



Modified text is an extract of the original Stack Overflow Documentation
Licensierat under CC BY-SA 3.0
Inte anslutet till Stack Overflow