151 votes

Ce n'static_assert faire, et qu'aimeriez-vous utiliser?

Pourriez-vous nous donner un exemple où l' static_assert(...) 'C++0x' permettrait de résoudre le problème de façon élégante?

Je suis familier avec le moment de l'exécution assert(...). Quand dois-je préfère static_assert(...) de plus régulières assert(...)?

Aussi, en boost il y a quelque chose qui s'appelle BOOST_STATIC_ASSERT, est-il le même que static_assert(...)?

169voto

AndreyT Points 139512

Statique affirmer, c'est utilisé pour faire des assertions au moment de la compilation. Lors de la statique de l'assertion échoue, le programme ne compile pas. Ceci est utile dans différentes situations, comme, par exemple, si vous mettez en œuvre certaines fonctionnalités par le code qui dépend de façon critique sur unsigned int objet ayant exactement 32 bits. Vous pouvez mettre un statique affirmer comme ceci

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

dans votre code. Sur une autre plate-forme, de taille différente unsigned int type de la compilation échouera, attirant ainsi l'attention de le développeur à la problématique de la portion de code et de les conseiller à re-mettre en œuvre ou de ré-inspecter.

Pour un autre exemple, vous pourriez souhaitez passer quelques intégrale de la valeur en tant que void * pointeur vers une fonction (un hack, mais utile à la fois) et que vous souhaitez assurez-vous que l'intégrale de la valeur de l'ajustement dans le pointeur

int i;

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

Vous pourriez atout char type est signé

static_assert(CHAR_MIN < 0);

ou que l'intégrale de la division avec des valeurs négatives tours vers zéro

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

Et ainsi de suite.

Au moment de l'exécution des assertions dans de nombreux cas, peut être utilisé à la place de la statique des assertions, mais au moment de l'exécution des affirmations fonctionnent uniquement au moment de l'exécution, et seulement lorsque le contrôle passe au-dessus de l'assertion. Pour cette raison, un défaut d'exécution affirmation peut latente, d'inaperçue pendant de longues périodes de temps.

Bien sûr, l'expression statique affirmation doit être une constante de compilation. Il ne peut pas être une valeur d'exécution. Pour les valeurs d'exécution que vous n'avez pas d'autre choix que d'utiliser l'ordinaire, assert.

89voto

Mark Rushakoff Points 97350

Sur le dessus de ma tête...

#include "SomeLibrary.h"

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

class UsingSomeLibrary {
   // ...
};

En supposant que l' SomeLibrary::Version est déclarée static const, plutôt que d'être #defined (comme on pourrait s'y attendre dans une bibliothèque C++).

Le contraste avec le fait d'avoir à compiler SomeLibrary et de votre code, tout lien, et lancez l'exécutable seulement ensuite pour savoir que vous avez passé 30 minutes de la compilation d'une version incompatible SomeLibrary.

@Arak, en réponse à votre commentaire: oui, vous pouvez avoir static_assert juste assis là où, à partir de l'apparence de celui-ci:

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
un.rpc:7: erreur: statique échec de l'assertion: "Foo::bar est trop petit :("

14voto

Matt Joiner Points 29194

Je l'utilise pour m'assurer que mes hypothèses sur comportement du compilateur, en-têtes, des bibliothèques et même mon propre code sont corrects. Par exemple ici, j'ai vérifier que la structure a été correctement emballés à la taille attendue.

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

Dans une classe d'habillage stdio.hs' fseek(), j'ai pris quelques raccourcis enum Origin et de vérifier que ces raccourcis aligner avec les constantes définies par l' stdio.h

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

Vous devriez préférer static_assert sur assert lorsque le comportement est défini au moment de la compilation, et non pas au moment de l'exécution, comme les exemples que j'ai donné ci-dessus. Un exemple où ce n'est pas le cas, inclure paramètre et retourne le code de vérification.

BOOST_STATIC_ASSERT est un pré-C++0x macro qui génère illégal code si la condition n'est pas satisfaite. Les intentions sont les mêmes, quoique static_assert est standardisée et peut fournir de meilleures compilateur diagnostics.

10voto

nurettin Points 4083

BOOST_STATIC_ASSERT est une croix-plate-forme de l'enveloppe pour static_assert fonctionnalités.

Actuellement, je suis en utilisant static_assert afin d'appliquer des "Concepts" sur une classe.

exemple:

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

Cela provoquera une erreur de compilation si l'une des conditions ci-dessus ne sont pas remplies.

9voto

Greg Hewgill Points 356191

Une utilisation de l' static_assert peut-être pour s'assurer qu'une structure (qui est une interface avec le monde extérieur, tel qu'un réseau ou d'un fichier) est exactement la taille que vous attendez. Ce serait attraper cas où quelqu'un ajoute ou modifie un membre de la structure sans réaliser les conséquences. L' static_assert le ramasser et d'alerte à l'utilisateur.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X