J'ai besoin d'accéder à un static constexpr
et une solution que j'ai mise en place fonctionne avec gcc ( live exemple ) mais pas avec vc ++ ( exemple en direct ).
Le code est le suivant:
template<class Drvd> class Base { public: static constexpr bool val = Drvd::val; }; class Derived : public Base<Derived> { friend class Base; private: static constexpr bool val = true; }; int main() { std::cout << Derived::Base::val << std::endl; }
C'est donc un bogue avec vc ++, mais n'importe qui a une idée sur la façon d'atteindre le val
défini dans Base
comme valeur de val
dans Drvd
d'une manière différente dont vc ++ ne se plaindra pas?
Modifier:
Notez que le résultat est le même avec la variante: friend class Base
au lieu de friend class Base;
3 Réponses :
Vous pouvez utiliser une méthode:
#include <iostream> template<class Drvd> class Base { public: static constexpr bool val() { return Drvd::val; } }; class Derived : public Base<Derived> { friend class Base<Derived>; private: static constexpr bool val = true; }; int main() { std::cout << Derived::Base::val() << std::endl; }
exemple en direct: https: // rextester .com / IHR24393
Belle variante, mais je devrais recourir à l'ajout de ()
. Si rien d'autre, je suppose que cela devrait faire. Merci.
Un autre commentaire, utilisant une fonction constexpr
, tout en travaillant pour ce cas particulier, est également limitant de pouvoir utiliser val ()
comme paramètre de modèle.
votre problème ne concerne pas les déclarations private / friend (le code ne se compilerait pas même si "val" était un public), votre problème est que lors de l'instanciation de
static constexpr bool val = Drvd::val
Drvd est encore de type incomplet. Voir ci-dessous la question / réponse pour savoir comment contourner ce problème avec les classes de traits.
Polymorphisme statique C ++ (CRTP) et utilisation de typedefs de classes dérivées
PS en fait, je viens de signaler votre question comme étant en double
merci, cela semble être la bonne direction. Bien que je ne sois pas sûr qu'il s'agisse directement d'un doublon, je vais essayer de jouer avec les informations de l'autre page et de voir quels résultats.
Selon @David, le problème vient du fait que Face
est incomplète, car il entre dans Base
avant de terminer la définition de Face
.
Cependant, la solution liée par @David est un peu ancienne et manque quelques astuces dont nous pouvons profiter. À savoir, @ m.s. nous montre que les fonctions static constexpr
sont très bien - et aussi basées sur ma propre expérimentation - et que nous n'avons vraiment besoin de traiter que ce cas particulier des variables static constexpr
, et peut-être des types accessible depuis Derived
.
Ce qui suit ( exemple en direct ) montre comment résoudre ce problème, tout en gardant chaque classe encapsulée dans son propre fichier h, ce qui le rend un peu plus propre:
#include <iostream> // Begin: h-file of Base template<class Drvd> class ConstValue; template<class Drvd> class Base { public: static constexpr bool val = ConstValue<Drvd>::val; }; // End: h-file of Base // Begin: h-file of Derived class Derived; template<> class ConstValue<Derived> { public: static constexpr bool val = true; }; class Derived : public Base<Derived> { friend class Base<Derived>; private: static constexpr bool val = true; // optional }; // End: h-file of Derived // Main int main() { std::cout << Derived::Base::val << std::endl; }
L'idée générale est que pour chaque constexpr
à laquelle Base
doit accéder depuis Derived
, nous pouvons créer une classe unique qui encapsule les variables, puis surcharger la classe pour chaque Derived code> qui utilise
Base
.
Copie possible de polymorphisme statique C ++ (CRTP) et utilisant des typedefs à partir de classes dérivées