Domanda

Potresti fare un esempio in cui static_assert (...) 'C ++ 0x' risolverebbe elegantemente il problema?

Conosco runtime (...) . Quando dovrei preferire static_assert (...) rispetto al normale assert (...) ?

Inoltre, in boost c'è qualcosa chiamato BOOST_STATIC_ASSERT , è lo stesso di static_assert (...) ?

È stato utile?

Soluzione

Fuori dalla cima della mia testa ...

#include "SomeLibrary.h"

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

class UsingSomeLibrary {
   // ...
};

Supponendo che SomeLibrary :: Version sia dichiarato come const statico, piuttosto che #define d (come ci si aspetterebbe in una libreria C ++).

Contrasto con la necessità di compilare effettivamente SomeLibrary e il tuo codice, collegare tutto ed eseguire l'eseguibile solo quindi per scoprire che hai impiegato 30 minuti a compilare una versione incompatibile di SomeLibrary .

@Arak, in risposta al tuo commento: sì, puoi avere static_assert semplicemente seduto ovunque, dall'aspetto:

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 :("

Altri suggerimenti

L'asserzione statica viene utilizzata per fare asserzioni in fase di compilazione. Quando l'asserzione statica fallisce, il programma semplicemente non viene compilato. Ciò è utile in diverse situazioni, come ad esempio se si implementano alcune funzionalità per codice che dipendono in modo critico dall'oggetto unsigned int con esattamente 32 bit. Puoi inserire un'asserzione statica come questa

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

nel tuo codice. Su un'altra piattaforma, con tipo unsigned int di dimensioni diverse, la compilazione non riuscirà, attirando così l'attenzione dello sviluppatore sulla parte problematica del codice e consigliandoli di reimplementarlo o riesaminarlo.

Per un altro esempio, potresti voler passare un valore integrale come puntatore void * a una funzione (un hack, ma a volte utile) e vuoi assicurarti che il valore integrale inserirsi nel puntatore

int i;

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

Potresti voler assegnare quel tipo di char firmato

static_assert(CHAR_MIN < 0);

o quella divisione integrale con valori negativi viene arrotondata allo zero

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

E così via.

In molti casi è possibile utilizzare asserzioni di runtime invece di asserzioni statiche, ma le asserzioni di runtime funzionano solo in fase di runtime e solo quando il controllo passa sull'asserzione. Per questo motivo un'affermazione di runtime non riuscita può rimanere inattiva, non rilevata per lunghi periodi di tempo.

Ovviamente, l'espressione nell'asserzione statica deve essere una costante di compilazione. Non può essere un valore di runtime. Per i valori di runtime non hai altra scelta che utilizzare il normale assert .

Lo uso per garantire che le mie ipotesi sul comportamento del compilatore, le intestazioni, le librerie e persino il mio codice siano corrette. Ad esempio, qui verifico che la struttura sia stata imballata correttamente nella dimensione prevista.

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

In una classe che racchiude il stdio.h fseek () , ho preso alcune scorciatoie con enum Origin e ho verificato che quelle scorciatoie allineare con le costanti definite da stdio.h

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

Dovresti preferire static_assert rispetto a assert quando il comportamento è definito in fase di compilazione e non in fase di esecuzione, come gli esempi che ho dato sopra. Un esempio in cui non il caso includerebbe il controllo dei parametri e del codice di ritorno.

BOOST_STATIC_ASSERT è una macro 0x pre-C ++ che genera codice non valido se la condizione non è soddisfatta. Le intenzioni sono le stesse, sebbene static_assert sia standardizzato e possa fornire una migliore diagnostica del compilatore.

BOOST_STATIC_ASSERT è un wrapper multipiattaforma per la funzionalità static_assert .

Attualmente sto usando static_assert al fine di imporre "concetti" su una lezione.

Esempio:

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 ... */
};

Ciò causerà un errore di tempo di compilazione se una delle condizioni di cui sopra non è soddisfatta.

Un uso di static_assert potrebbe essere quello di garantire che una struttura (che è un'interfaccia con il mondo esterno, come una rete o un file) abbia esattamente le dimensioni che ci si aspetta. Ciò catturerebbe i casi in cui qualcuno aggiunge o modifica un membro dalla struttura senza rendersene conto. Il static_assert lo prenderebbe e avviserebbe l'utente.

In assenza di concetti si può usare static_assert per un controllo del tipo di compilazione semplice e leggibile, ad esempio nei template:

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

// ...
}

Questo non risponde direttamente alla domanda originale, ma fa uno studio interessante su come applicare questi controlli del tempo di compilazione prima di C ++ 11.

Il capitolo 2 (sezione 2.1) di Design moderno in C ++ di Andrei Alexanderscu implementa questo idea di asserzioni in fase di compilazione come questa

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

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

Confronta la macro STATIC_CHECK () e static_assert ()

STATIC_CHECK(0, COMPILATION_FAILED);
static_assert(0, "compilation failed");
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top