Observez le programme suivant dans lequel une fonction accepte à la fois le type attendu et tout type qui est un type TYPEDEF de ce type.
//I want the functionality, but these are NOT the same type! class Gadget: public Widget{ operator Widget() = delete; };
3 Réponses :
Peut-être que vous pourriez utiliser l'héritage privé et certains en utilisant code> S?
class Gadget : Widget { using Widget::Widget; using Widget::foo; ... };
Je pense que c'est une solution correcte en supposant qu'il n'y ait pas trop de méthodes ou de membres de données pour énumérer.
En gros, vous avez besoin de deux classes non liées avec le même comportement. J'utiliserais un modèle paramétré pour cela:
template<int tag> class WidgetGadget { ... }; typedef WidgetGadget<0> Widget; typedef WidgetGadget<1> Gadget;
boost_strong_typedf suppose en fait que les types sont équatables ( Si votre type n'est pas, la macro donne le code de code qui ne compile pas, comme vous avez été témoin. Vous pouvez faire rouler votre propre macro ou fournir des implémentations pour les opérations requises. P> Vous pouvez trouver un Mise à jour forte> a rendu l'exemple plus explicite pour votre cas d'utilisation, le voir Vivez sur Coliru strong> p> == code>), assignable (
= code>) et moins que comparable (
).
personnalisé_strong_typef code> dans cette réponse de Februari 2012: Comment utiliser des opérateurs de comparaison sur la variante avec des types contenus? strong>, qui évite explicitement l'obtention du comportement de comparaison par défaut P>
//a user defined type
class Widget{};
class Frobnicator{};
/////////////////////////////////////////////////////
// copied and reduced from boost/strong_typedef.hpp
#define CUSTOM_STRONG_TYPEDEF(T, D) \
struct D \
/*: boost::totally_ordered1< D */ \
/*, boost::totally_ordered2< D, T */ \
/*> > */ \
{ \
T t; \
explicit D(const T t_) : t(t_) {}; \
D(){}; \
D(const D & t_) : t(t_.t){} \
D & operator=(const D & rhs) { t = rhs.t; return *this;} \
D & operator=(const T & rhs) { t = rhs; return *this;} \
explicit operator const T & () const {return t; } \
explicit operator T & () { return t; } \
/*bool operator==(const D & rhs) const { return t == rhs.t; } */\
/*bool operator<(const D & rhs) const { return t < rhs.t; } */\
};
CUSTOM_STRONG_TYPEDEF(Widget, Gadget)
CUSTOM_STRONG_TYPEDEF(Frobnicator, Normalcy)
void acceptWidget(Widget){}
void acceptGadget(Gadget){}
void acceptFrobnicator(Frobnicator){}
void acceptNormalcy(Normalcy){}
int main(){
//make the two "different types" (well.. they're not really different as you will see)
Widget w;
Gadget g;
//call a function that should ONLY accept Widgets
acceptWidget(w); //works (good)
acceptGadget(g);
//acceptWidget(g); // Error
//acceptGadget(w); // Error
// but we can enjoy conversions if we summon them
acceptWidget(static_cast<Widget&>(g));
Frobnicator f;
Normalcy n;
acceptFrobnicator(f);
acceptNormalcy(n);
}
Travailler pour le problème donné dans la question initiale, il faudrait commenter les deux dernières méthodes pour l'opérateur T. Il s'agit d'une solution OK, mais il faudrait être réécrit à nouveau et à nouveau pour traiter différents types, et donc Les macros devraient être nommées de manière unique.
Je ne vois pas ce que tu veux dire. Je viens de citer principalement l'autre réponse. Mais, en faisant les conversions explicites code> fera-t-il, et non, vous n'avez pas à écrire cela sur et plus? Mise à jour ma réponse. Voyez-le Vivez sur Coliru **
Ah! Je vois à propos de l'explicite maintenant. J'ai ajouté votre exemple de programme pour illustrer la manière dont cette macro ne peut être utilisée que pour un type de fonctionnalité de classe. Ainsi, je devrais écrire plusieurs macros pour gérer ces différents cas. Coliru.stacked-crooked.com/a/8D80373EBD596C61
@Trevorhickey oh. Bien. Je reçois cela maintenant, mais cela n'a jamais été une partie de votre question: s. Leçon: Avoir les conditions requises est essentielle pour obtenir la bonne solution i>. Notez également que je do b> répondez également à la première partie (1.) de votre question, contrairement à l'une des autres réponses. Je pense que vous voudrez utiliser la réponse de Grep, mais ce n'est pas ce que vous avez posé sur: /
Je suppose que je vais
class widgetbase code>, et do
widget de classe: widget publicbase code>;
Gadget de classe: Widget publicbase code>.
@zneak: C'est ce que
boost_strong_typedf code> fait.
@DEduplicator en regardant la mise en œuvre STORT_TYPEDEF utilise un membre et non sur l'héritage.
Ce n'est pas que Strong_typedf ne fonctionne que pour des types primitifs, mais il faut que le type d'argument soit totalement commandé (
opérateur == code>,
opérateur << / code>) Vous pouvez peut-être leur fournir ou simplement utiliser le code de forte_typedf moins la commande.
@PMR: Voyez-vous toujours un message Zneaks? Je ne.
@PMR "Pourquoi cela nécessite-t-il de commander?" Je me demande.
Vous voulez un type
gadget code> qui est comme
widget code> mais pas comme
widget code>. Cela aiderait-il à prendre un pas en arrière et à réfléchir à ce que vous essayez de déclarer?
@Trevor: Probablement au plus profond de la sérialisation de Boost. Néanmoins, n'a pas trouvé d'endroit mais les sources où elle est documentée.
Je suppose que vous voulez avoir fonctions mutuellement exclusives i> pour les deux types? Parce que si la barrière ne doit fonctionner que dans une voie, vous pouvez simplement inverser la relation héritabilité (vous pouvez toujours trancher, mais non implicitement jeté).
Pour des fonctions mutuellement exclusives, vous pouvez rendre le widget et le gadget hériter d'une base commune.