Frage

Können Sie ein Beispiel geben, wo static_assert(...) 'C++0x' das Problem in der Hand lösen würde elegant?

Ich bin mit der Laufzeit assert(...). Wann sollte ich static_assert(...) über regelmäßige assert(...) bevorzugen?

Auch in boost gibt es etwas namens BOOST_STATIC_ASSERT, wird es das gleiche wie static_assert(...)?

War es hilfreich?

Lösung

Aus der Spitze von meinem Kopf ...

#include "SomeLibrary.h"

static_assert(SomeLibrary::Version > 2, 
         "Old versions of SomeLibrary are missing the foo functionality.  Cannot proceed!");

class UsingSomeLibrary {
   // ...
};

Unter der Annahme, dass SomeLibrary::Version als static const deklariert wird, anstatt #defined wird (wie man in einer C ++ Bibliothek erwarten würde).

Kontrast mit, die tatsächlich SomeLibrary und Ihren Code zu kompilieren, alles verknüpfen und die ausführbare Datei nur und , um herauszufinden, dass Sie 30 Minuten verbrachten eine inkompatible Version von SomeLibrary kompilieren.

@Arak, in Reaktion auf Ihren Kommentar: ja, können Sie static_assert nur noch sitzen, wo immer, aus dem es aussieht:

class Foo
{
    public: 
        static const int bar = 3;
};

static_assert(Foo::bar > 4, "Foo::bar is too small :(");

int main()
{ 
    return Foo::bar;
}
$ g++ --std=c++0x a.cpp
a.cpp:7: error: static assertion failed: "Foo::bar is too small :("

Andere Tipps

Statische assert verwendet Behauptungen bei der Kompilierung zu machen. Wenn die statische Behauptung fehlschlägt, wird das Programm einfach nicht kompilieren. Dies ist nützlich, in verschiedenen Situationen, wie zum Beispiel, wenn Sie einige Funktionen von Code implementieren, die auf unsigned int Objekt hängt entscheidend mit genau 32 Bit. Sie können eine statische assert so sagen

static_assert(sizeof(unsigned int) * CHAR_BIT == 32);

in Ihrem Code. Auf einer anderen Plattform, mit unterschiedlich großen unsigned int die Zusammenstellungsart wird fehlschlagen, so dass die Aufmerksamkeit des Entwicklers auf den problematischen Teil des Codes zeichnen und Beratung sie neu zu implementieren oder neu inspizieren.

Für ein anderes Beispiel, möchten Sie vielleicht etwas festen Wert als void * Zeiger auf eine Funktion zu übergeben (ein Hack, aber nützlich manchmal), und Sie wollen sicherstellen, dass der Integralwert in die Zeiger paßt

int i;

static_assert(sizeof(void *) >= sizeof i);
foo((void *) i);

Sie möchten vielleicht Vermögenswert, der Typ char unterzeichnet

static_assert(CHAR_MIN < 0);

oder dass ganzzahlige Division mit negativen Werten gegen Null rundet

static_assert(-5 / 2 == -2);

Und so weiter.

Laufzeit Behauptungen in vielen Fällen anstelle von statischen Behauptungen verwendet werden, aber die Laufzeit Behauptungen nur zur Laufzeit arbeiten und nur dann, wenn die Kontrolle über die Behauptung geht. Aus diesem Grund ist ein Fehler Laufzeit Behauptung kann ruhend, unentdeckt für längere Zeit legen.

Natürlich ist der Ausdruck in statischer Behauptung hat ein Kompilierung-Konstante sein. Es kann kein Laufzeitwert sein. Für Laufzeitwerte haben Sie keine andere Wahl, als die gewöhnlichen assert verwenden.

Ich benutze es, um meine Annahmen über Compiler Verhalten, headers, Libs und sogar meinen eigenen Code korrekt sind zu gewährleisten. Zum Beispiel hier prüfe ich, dass die Struktur der erwarteten Größe korrekt verpackt wurde.

struct LogicalBlockAddress
{
#pragma pack(push, 1)
    Uint32 logicalBlockNumber;
    Uint16 partitionReferenceNumber;
#pragma pack(pop)
};
BOOST_STATIC_ASSERT(sizeof(LogicalBlockAddress) == 6);

In einer Klasse Verpackung stdio.h der fseek(), habe ich einige Abkürzungen mit enum Origin genommen und prüfen, ob diese Verknüpfungen mit den Konstanten ausrichten, indem stdio.h definiert

uint64_t BasicFile::seek(int64_t offset, enum Origin origin)
{
    BOOST_STATIC_ASSERT(SEEK_SET == Origin::SET);

Sie sollten static_assert über assert bevorzugen, wenn das Verhalten bei der Kompilierung definiert und zur Laufzeit nicht, wie die Beispiele, die ich oben gegeben habe. Ein Beispiel, wo dies ist nicht der Fall wäre Parameter umfassen und Return-Code zu überprüfen.

BOOST_STATIC_ASSERT ist ein Pre-C ++ 0x-Makro, das illegal Code generiert, wenn die Bedingung nicht erfüllt ist. Die Absichten sind die gleichen, wenn auch static_assert standardisiert und kann besser Compiler Diagnose liefern.

BOOST_STATIC_ASSERT ist ein Cross-Plattform-Wrapper für static_assert Funktionalität.

Derzeit bin ich mit static_assert um „Konzepte“ für eine Klasse zu erzwingen.

Beispiel:

template <typename T, typename U>
struct Type
{
  BOOST_STATIC_ASSERT(boost::is_base_of<T, Interface>::value);
  BOOST_STATIC_ASSERT(std::numeric_limits<U>::is_integer);
  /* ... more code ... */
};

Dies wird eine Kompilierung Fehler verursachen, wenn eine der oben genannten Bedingungen nicht erfüllt ist.

Eine Verwendung von static_assert könnte sein, um sicherzustellen, dass eine Struktur (dh eine Schnittstelle mit der Außenwelt, wie zum Beispiel ein Netzwerk oder Datei) ist genau die Größe, die Sie erwarten. Dies würde Fälle fangen, wenn jemand hinzufügt oder ändert ein Mitglied aus der Struktur, ohne die Konsequenzen zu realisieren. Die static_assert würde es abholen und die Benutzer alarmieren.

In Abwesenheit von Konzepten ein static_assert für eine einfache und lesbare Kompilierung Typüberprüfung, zum Beispiel in Vorlagen verwenden kann:

template <class T>
void MyFunc(T value)
{
static_assert(std::is_base_of<MyBase, T>::value, 
              "T must be derived from MyBase");

// ...
}

Dies ist nicht direkt beantwortet die ursprüngliche Frage, sondern macht eine interessante Studie darüber, wie diese Zeit zu erzwingen Kontrollen vor C ++ 11 kompilieren.

Kapitel 2 (Abschnitt 2.1) von Moderne C ++ Entwurf von Andrei Alexanderscu implementiert diese Idee von Compile-Zeit Behauptungen wie diese

template<int> struct CompileTimeError;
template<> struct CompileTimeError<true> {};

#define STATIC_CHECK(expr, msg) \
{ CompileTimeError<((expr) != 0)> ERROR_##msg; (void)ERROR_##msg; } 

Vergleichen Sie die Makro STATIC_CHECK () und static_assert ()

STATIC_CHECK(0, COMPILATION_FAILED);
static_assert(0, "compilation failed");
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top