2016-03-06 1 views
4

Je rencontre souvent des situations où je dois implémenter des constructeurs de copie/déplacement personnalisés. Cependant, quelque temps plus tard, il arrive que la classe soit étendue avec un nouveau membre et que ce constructeur de copie/déplacement personnalisé ne soit pas mis à jour, donc je cherche un moyen d'empêcher la compilation du code sans mettre à jour ces méthodes.Comment obtenir le nombre de membres dans une classe au moment de la compilation

Code d'en-tête:

class MyClass 
    { 
    public: 
     MyClass(const MyClass &rhs); 
     // ... 
    private: 
     std::string     _s; 
     std::unique_ptr<OtherClass> _owned; 
     bool      _b; 
    }; 

Code Cpp:

MyClass::MyClass(const MyClass &rhs) 
    : _s(rhs._s) 
    , _b(rhs._b) 
    { 
    if (rhs._owned) 
     _owned = rhs._owned->clone(); 
    } 

Donc, si j'ajouter quelque membre à MyClass, par exemple: std::size_t _size; que je voudrais une erreur de compilation pour le constructeur de copie.

Ma solution actuelle est d'ajouter:

static_assert(sizeof(MyClass) == 32, "..."); 

près de cette mise en œuvre du constructeur de copie. Tout cela fonctionne très bien, malheureusement cela ne fonctionne que lorsque la taille de la classe augmente. Donc, si je ajoute à la place bool _b2;, tout compile malheureusement.

Donc, au lieu de vérifier la taille, je voudrais vérifier le nombre de membres. Malheureusement, je ne l'ai pas encore trouvé. Y a-t-il des suggestions?

Je l'ai déjà considéré:

  • interdiction bool en faveur de short, mais il brise tout sens de l'intention.
  • remplaçant bool par bitset, mais des valeurs différentes ne peuvent pas avoir des noms différents
  • Mettez tous par défaut des membres copiables dans struct séparé, qui introduit la complexité
  • Ajouter static const auto avec le nombre de membres à la classe, en espérant que cela est mis à jour le l'ajout d'un membre

Toutes ces idées ont cependant besoin de changements de code/directives, donc idéalement je voudrais juste écrire static_assert(number_of_members<MyClass>::value == 3, "...");, des idées?

+1

Je ne pense pas qu'il existe un moyen d'obtenir le nombre de membres de la classe en utilisant le langage lui-même. Espérons que quelqu'un de plus compétent que moi puisse prouver le contraire. –

+1

C++ n'a pas de réflexion statique, non. – Barry

+1

Un bon outil Lint devrait vous avertir lorsque des membres sont manquants dans les constructeurs, les affectations de copie, etc. – 1201ProgramAlarm

Répondre

6

Rule of Zero:

Les classes qui ont Destructeurs personnalisés, copier/déplacer des constructeurs ou copier/déplacer les opérateurs d'affectation doivent traiter exclusivement à la propriété (qui découle de la responsabilité unique Principe). Les autres classes ne doivent pas avoir de destructeurs personnalisés, copier/déplacer des constructeurs ou copier/déplacer des opérateurs d'affectation.

Dans ce cas, si vous avez simplement eu un:

template <class T> 
struct clone_unique_ptr { 
    std::unique_ptr<T> p; 

    clone_unique_ptr(const clone_unique_ptr& rhs) 
    : p(rhs.p ? rhs.p->clone() : nullptr) 
    { } 

    // rest of special members 
}; 

Ensuite, vous ne pas avoir à écrire quelque chose de spécial.

class MyClass 
{ 
public: 
    MyClass(const MyClass&) = default; 
private: 
    std::string     _s; 
    clone_unique_ptr<OtherClass> _owned; 
    bool       _b; 
}; 
+0

Cela fonctionnerait, si tout le code avait la même API, malheureusement le refactoring prend du temps: S et si vous souhaitez utiliser move-constructors dans MSVC2013, vous ne pouvez pas utiliser = par défaut. Cependant j'aime l'idée! Merci beaucoup! – JVApen

+0

Ce n'est pas ce que je cherchais, même si je crois que c'est la meilleure solution au problème. Donc je vais accepter ça. – JVApen

-1

C++ ne dispose pas reflection construit Cependant , vous pouvez essayer d'utiliser une bibliothèque externe xCppRefl qui devrait fournir une réflexion (N'a jamais utilisé auparavant et il est assez vieux alors laissez-moi savoir si l'utilisation de la bibliothèque fonctionne pour vous).

pas à pas à travers la source si vous

std::vector<DataMember> dataMembers = className.getDataMembers(); 

Et puis exécutez assert(dataMembers.size() == expectedNumMembers) vous devriez être en mesure de vérifier si le nombre de membres dans une classe est ce que vous attendez.

+1

Il veut une solution de compilation – Vincent