Suche…
Syntax
[[Details]]: Einfaches Argument ohne Argument
[[Details (Argumente)]]: Attribut mit Argumenten
__attribute (Details): Nicht GCC / Clang / IBM-spezifisch
__declspec (Details): Nicht-Standard MSVC-spezifisch
[[keine Rückkehr]]
In C ++ 11 wurde das Attribut [[noreturn]]
. Es kann für eine Funktion verwendet werden, um anzuzeigen, dass die Funktion nicht zum Aufrufer zurückkehrt, indem entweder eine return- Anweisung ausgeführt wird oder das Ende des Textes erreicht wird (es ist wichtig zu beachten, dass dies nicht für void
Funktionen gilt, da sie dies sind) kehren Sie zum Anrufer zurück, sie geben nur keinen Wert zurück. Eine solche Funktion kann mit dem Aufruf von std::terminate
oder std::exit
oder mit dem Auslösen einer Ausnahme std::terminate
. Es ist auch erwähnenswert, dass eine solche Funktion durch Ausführen von longjmp
.
Die folgende Funktion [[noreturn]]
zum Beispiel immer eine Ausnahme aus oder ruft std::terminate
, daher ist sie ein guter 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();
}
Durch diese Art von Funktionalität kann der Compiler eine Funktion ohne return-Anweisung beenden, wenn er weiß, dass der Code niemals ausgeführt wird. Da der Aufruf von ownAssertFailureHandler
(oben definiert) im nachstehenden Code niemals zurückgegeben wird, muss der Compiler hier keinen Code unter diesem Aufruf hinzufügen:
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]]
}
Es ist undefiniertes Verhalten, wenn die Funktion tatsächlich zurückkehrt. Folgendes ist nicht zulässig:
[[noreturn]] void assertPositive(int number) {
if (number >= 0)
return;
else
ownAssertFailureHandler("Positive number expected"s); //< [[noreturn]]
}
Beachten Sie, dass der [[noreturn]]
meist in void-Funktionen verwendet wird. Dies ist jedoch keine Voraussetzung, damit die Funktionen in der generischen Programmierung verwendet werden können:
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);
Die folgenden Standardbibliotheksfunktionen haben dieses Attribut:
- std :: abbrechen
- std :: exit
- std :: quick_exit
- std :: unerwartet
- std :: terminate
- std :: rethrow_exception
- std :: throw_with_nested
- std :: nested_exception :: rethrow_nested
[[durchfallen]]
Wenn ein case
in einem switch
, wird der Code des nächsten Falls ausgeführt. Letzteres kann mit der ´break'-Anweisung verhindert werden. Da dieses sogenannte Fallthrough-Verhalten zu Fehlern führen kann, wenn dies nicht beabsichtigt ist, warnen mehrere Compiler und statische Analysatoren dies.
Ab C ++ 17 wurde ein Standardattribut eingeführt, um anzuzeigen, dass die Warnung nicht erforderlich ist, wenn der Code durchfallen soll. Compiler können sicher [[fallthrough]]
wenn ein Fall ohne break
oder [[fallthrough]]
und mindestens eine Anweisung [[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;
}
In dem Vorschlag finden Sie detailliertere Beispiele, wie [[fallthrough]]
verwendet werden kann.
[[veraltet]] und [[veraltet ("Grund")]]
Mit C ++ 14 wurde eine Standardmethode eingeführt, um Funktionen über Attribute abzulehnen. [[deprecated]]
kann verwendet werden, um anzuzeigen, dass eine Funktion veraltet ist. [[deprecated("reason")]]
ermöglicht das Hinzufügen eines bestimmten Grunds, der vom Compiler angezeigt werden kann.
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);
Dieses Attribut kann angewendet werden auf:
- die Deklaration einer Klasse
- ein typedef-name
- eine Variable
- ein nicht statisches Datenelement
- eine Funktion
- eine Aufzählung
- eine Vorlagenspezialisierung
(Ref. C ++ 14 Standardentwurf : 7.6.5 Veraltetes Attribut)
[nodiscard]]
Das Attribut [[nodiscard]]
kann verwendet werden, um anzuzeigen, dass der Rückgabewert einer Funktion beim Funktionsaufruf nicht ignoriert werden soll. Wenn der Rückgabewert ignoriert wird, sollte der Compiler eine Warnung ausgeben. Das Attribut kann hinzugefügt werden:
- Eine Funktionsdefinition
- Eine Art
Das Hinzufügen des Attributs zu einem Typ hat dasselbe Verhalten wie das Hinzufügen des Attributs zu jeder einzelnen Funktion, die diesen Typ zurückgibt.
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
}
Siehe den Vorschlag für detailliertere Beispiele, wie [[nodiscard]]
verwendet werden kann.
Hinweis: Die Details der Implementierung Finally
/ onExit
sind in dem Beispiel weggelassen, siehe Schließlich / ScopeExit .
[[vielleicht_unused]]
Das Attribut [[maybe_unused]]
wird erstellt, um im Code [[maybe_unused]]
dass bestimmte Logik möglicherweise nicht verwendet wird. Dies wird häufig mit Präprozessor-Bedingungen verknüpft, bei denen dies verwendet werden kann oder nicht verwendet werden kann. Da Compiler zu nicht verwendeten Variablen Warnungen ausgeben können, können sie auf diese Weise durch Angabe von Absichten unterdrückt werden.
Ein typisches Beispiel für Variablen, die in Debugbuilds benötigt werden, während sie in der Produktion nicht benötigt werden, sind Rückgabewerte, die den Erfolg anzeigen. In den Debug-Builds sollte die Bedingung geltend gemacht werden, obwohl diese Assays in der Produktion entfernt wurden.
[[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
Ein komplexeres Beispiel sind verschiedene Arten von Hilfsfunktionen, die sich in einem unbenannten Namensraum befinden. Wenn diese Funktionen beim Kompilieren nicht verwendet werden, gibt der Compiler möglicherweise eine Warnung aus. Im Idealfall möchten Sie sie mit den gleichen Präprozessor-Tags wie der Aufrufer [[maybe_unused]]
dies jedoch komplex werden kann, ist das Attribut [[maybe_unused]]
eine eher wartbare Alternative.
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
}
In dem Vorschlag finden Sie detailliertere Beispiele zur Verwendung von [[maybe_unused]]
.