2009-05-26 9 views
0

Disons que j'ai 3 classes. Je m'attends à sizeof() chaque classe à être exactement les mêmes - disons 512 octets.Comment affirmer statiquement une propriété commune de plusieurs classes

Comment puis-je utiliser quelque chose comme BOOST_STATIC_ASSERT à appliquer à tous tels que

  1. Je ne dois utiliser BOOST_STATIC_ASSERT en un seul endroit (principe SEC)
  2. ÉVALUÉ une fois à la compilation et non run-time

note: nous pouvons utiliser ce que C++ techniques que nous voulons (créer plus de classe, utiliser l'héritage, etc.)

Ma solution naïve est présentée ci-dessous:

class A { ...stuff }; BOOST_STATIC_ASSERT(sizeof(A) == 512); 
class B { ...stuff }; BOOST_STATIC_ASSERT(sizeof(B) == 512); 
class C { ...stuff }; BOOST_STATIC_ASSERT(sizeof(C) == 512); 
+2

Pourquoi avez-vous besoin d'affirmer que toutes les tailles seront 512 (ou un autre nombre magique)? Je demande parce que cela vous dit habituellement si vous devez vous répéter et où un tel test devrait aller si vous ne voulez pas vous répéter. Par exemple, si 512 est la taille d'une ligne de cache, vous devez associer A, B et C avec un concept de "correspond exactement à une ligne de cache" et l'exprimer quelque part. – MSN

+0

La raison en est que toutes ces classes sont liées, bien que l'un des points communs est que leur taille doit être exactement de 512 octets. Alors pourquoi les différentes classes? C'est parce que A, B et C expriment différents types de messages. – sivabudh

Répondre

9

Cela semble fonctionner avec gcc 4.0.1 et stimuler 1,39:


template <typename T, size_t S> 
struct enforce_size 
{ 
    enforce_size() 
    { 
     BOOST_STATIC_ASSERT(sizeof(T) == S); 
    } 
}; 

class A: enforce_size<A,512> { /* stuff */ }; 
 
+0

+1: Vous avez été plus rapide que moi: D – Klaim

+0

Bien que le message d'erreur nécessite un peu de travail :) –

+0

Bravo, Nikolai. –

1

Comme ces classes ont aucune relation, je vois maintenant façon de le faire parce que vous devez être explicite sur les types de sorcières que vous voulez vérifier.

La seule manière DRY d'appliquer ceci est ce que Nikolai N Festissov a proposé. J'écrivais un exemple similaire avec quelques modifications mineures, mais l'idée globale est de faire une classe boost :: nocopy-like qui va forcer la classe enfant à avoir une taille donnée.

template< typename CheckedType, size_t FixedSize > 
class SizeChecked // simple, no inheritance overload 
{ 
public: 
    SizeChecked() 
    { 
     // c++0x or compilers with static_assert() available 
     //static_assert(sizeof(CheckedType) == FixedSize, "Type size check failed!"); 
     BOOST_STATIC_ASSERT(sizeof(CheckedType) == FixedSize); 
    } 

}; 

template< typename CheckedType > 
class Size512 : public SizeChecked< CheckedType, 512 > // simple, no inheritance overload 
{}; 

//////////////////////////////////////////////////////////////////// 

class A : Size512<A> // automatically check 
{ 
}; 


class B : Size512<B> // automatically check 
{ 
    std::array< char, 512 > m_array; 
}; 

class C : SizeChecked< C, 1 > 
{ 
    char m_char; 
}; 

class D : SizeChecked< D, 4 > 
{ 
    short m_k; 
    char m_u; 

}; 


int wmain() 
{ 
    // need instantiation to be checked ! 
    //A a; // will trigger the assertion at compile time 
    B b; // sizeof(B) == 512 : will be fine 
    C c; // sizeof(C) == 1 : will be fine 
    //D d; // will fail because sizeof(short) + sizeof(char) != 4 ! 

} 

Attention: si vous avez l'héritage libre vous reste à fournir un contrôle explicite sur les classes d'enfants, le chèque est pas hérité! A propos, une manière possible d'être plus DRY serait de mettre toutes vos affirmations statiques en un seul endroit.

Questions connexes