Ricerca…


Sintassi

  • [[dettagli]]: Semplice attributo senza argomento

  • [[dettagli (argomenti)]]: Attributo con argomenti

  • __attribute (dettagli): GCC / Clang / IBM non standard specifici

  • __declspec (dettagli): specifico MSVC non standard

[[senza ritorno]]

C ++ 11

C ++ 11 ha introdotto l'attributo [[noreturn]] . Può essere usato per una funzione per indicare che la funzione non ritorna al chiamante eseguendo un'istruzione return o raggiungendo la fine se è body (è importante notare che questo non si applica alle funzioni void , poiché non tornare al chiamante, semplicemente non restituiscono alcun valore). Tale funzione può terminare chiamando std::terminate o std::exit o lanciando un'eccezione. Vale anche la pena notare che tale funzione può tornare eseguendo longjmp .

Ad esempio, la funzione seguente genera sempre un'eccezione o chiama std::terminate , quindi è un buon candidato per [[noreturn]] :

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

Questo tipo di funzionalità consente al compilatore di terminare una funzione senza un'istruzione return se sa che il codice non verrà mai eseguito. Qui, poiché la chiamata a ownAssertFailureHandler (definita sopra) nel codice seguente non tornerà mai più, il compilatore non ha bisogno di aggiungere il codice sotto quella chiamata:

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

È un comportamento non definito se la funzione verrà effettivamente restituita, quindi non è consentito quanto segue:

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

Nota che [[noreturn]] è usato principalmente nelle funzioni void. Tuttavia, questo non è un requisito, consentendo di utilizzare le funzioni nella programmazione generica:

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

Le seguenti funzioni di libreria standard hanno questo attributo:

  • std :: Abort
  • std :: uscita
  • std :: quick_exit
  • std :: inaspettato
  • std :: terminare
  • std :: rethrow_exception
  • std :: throw_with_nested
  • std :: :: nested_exception rethrow_nested

[[sfumare]]

C ++ 17

Ogni volta che un case termina in un switch , il codice del caso successivo verrà eseguito. Quest'ultimo può essere prevenuto usando l'istruzione'break`. Dato che questo cosiddetto comportamento anticaduta può introdurre bug quando non lo si intende, diversi compilatori e analizzatori statici forniscono un avvertimento su questo.

Da C ++ 17 in poi, è stato introdotto un attributo standard per indicare che l'avviso non è necessario quando il codice è destinato a cadere. I compilatori possono tranquillamente dare avvertimenti quando un caso è terminato senza break o [[fallthrough]] e ha almeno una dichiarazione.

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

Vedi la proposta per esempi più dettagliati su come [[fallthrough]] può essere usato.

[[deprecato]] e [[deprecato ("motivo")]]

C ++ 14

C ++ 14 ha introdotto un modo standard di deprecare le funzioni tramite attributi. [[deprecated]] può essere usato per indicare che una funzione è deprecata. [[deprecated("reason")]] consente di aggiungere un motivo specifico che può essere mostrato dal compilatore.

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

Questo attributo può essere applicato a:

  • la dichiarazione di una classe
  • un nome typedef
  • una variabile
  • un membro dati non statico
  • una funzione
  • un'enumerazione
  • una specializzazione di modello

( riferimento alla bozza standard di c ++ 14 : 7.6.5 Attributo deprecato)

[[Nodiscard]]

C ++ 17

L'attributo [[nodiscard]] può essere utilizzato per indicare che il valore di ritorno di una funzione non deve essere ignorato quando si effettua una chiamata di funzione. Se il valore di ritorno viene ignorato, il compilatore dovrebbe dare un avvertimento su questo. L'attributo può essere aggiunto a:

  • Una definizione di funzione
  • Un tipo

Aggiungere l'attributo a un tipo ha lo stesso comportamento di aggiungere l'attributo a ogni singola funzione che restituisce questo tipo.

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
}

Vedi la proposta per esempi più dettagliati su come [[nodiscard]] può essere usato.

Nota: i dettagli di implementazione di Finally / onExit sono omessi nell'esempio, vedi Finally / ScopeExit .

[[Maybe_unused]]

L'attributo [[maybe_unused]] viene creato per indicare nel codice che alcune logiche potrebbero non essere utilizzate. Questo, se spesso collegato alle condizioni del preprocessore dove potrebbe essere utilizzato o non può essere utilizzato. Poiché i compilatori possono dare avvertimenti su variabili non utilizzate, questo è un modo per sopprimerle indicando l'intenzione.

Un tipico esempio di variabili che sono necessarie nelle build di debug mentre non necessarie nella produzione sono valori di ritorno che indicano il successo. Nelle build di debug, la condizione dovrebbe essere asserita, sebbene in produzione questi assert siano stati rimossi.

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

Un esempio più complesso è un diverso tipo di funzioni di aiuto che si trovano in uno spazio dei nomi senza nome. Se queste funzioni non vengono utilizzate durante la compilazione, un compilatore potrebbe dare un avvertimento su di esse. Idealmente ti piacerebbe proteggerli con gli stessi tag del preprocessore del chiamante, anche se questo potrebbe diventare complesso l'attributo [[maybe_unused]] è un'alternativa più [[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
}

Vedi la proposta per esempi più dettagliati su come [[maybe_unused]] può essere usato.



Modified text is an extract of the original Stack Overflow Documentation
Autorizzato sotto CC BY-SA 3.0
Non affiliato con Stack Overflow