Comment puis-je simplifier ce code?
mfer::i_value* make_empty_value(mfer::tag tag_) { return memory_manager::instance().add(new mfer::t_value<tag_>()); }
mff-mfre :: étiquette est énumération, définie comme mffre :: i_value est une classe abstraite. P>
MFF MFER :: T_Value est une classe modélisée comme, p>
Enum tag {}; code> dans l'espace de noms de noms. p> li>
template <mfer::tag tag_type>
class t_value : public i_value {};
class i_value {};
5 Réponses :
Pas directement à l'aide de votre exemple, mais vous pouvez faire quelque chose sur les lignes ci-dessous, c'est convertir Enum en un type.
enum Type { Type_A, Type_B, }; template <Type T> struct Enum2Type { constexpr static const Type type = T; }; template <typename T> mfer::i_value* make_empty_value(T tag_type) { return memory_manager::instance().add(new mfer::t_value<tag_type.type>()); } auto val = make_empty_value(Enum2Type<Type_A>()); auto val2 = make_empty_value(Enum2Type<Type_B>());
Mais si j'utilise ce code, je ne peux pas passer de la variable à travers cette fonction, n'est-ce pas?
Si vous voulez dire faire l'argument de make_empty_value code> variable, alors non, vous ne pouvez pas. Un modèle nécessite une certaine valeur qu'il peut voir une heure de compilation. À un moment donné, vous devrez utiliser un cas de commutation si son paramètre d'exécution.
Je vois. ; (Je m'attendais à ce que la situation puisse mettre en œuvre de cette façon sera plus habituelle, alors je croyais qu'il y ait un modèle pour ces codes.
Une autre façon serait d'utiliser code> Dispatching code> dans le constructeur de MFF :: t_value code>. Dans ce cas, vous n'avez pas besoin d'écrire le boîtier de commutation dans
make_empty_value code>, mais il devra ensuite créer un constructeur pour chaque valeur d'énorme. Donc, vous voyez, à un moment donné, vous devrez développer toutes vos options si vous utilisez le paramètre d'exécution :)
Vous pouvez mapper les balises sur une méthode d'usine;
mfer::i_value* make_empty_value(mfer::tag tag_) { static TagMap factory = create_tag_map(); auto it = factory.find( tag_ ); if( it != factory.end() ) { return memory_manager::instance().add( it->second() ); } return nullptr; }
Mais s'il n'en utilise qu'une seule fois, il écrit même plus i> code pour créer le modèle d'usine pour une utilisation unique.
Vous pouvez créer une fonction de modèle récursif si la valeur énumérée suit un motif connu (par défaut la valeur énumérée suivante est égale à énumérer +1): si vous ne connaissez pas la constitutive Règle de votre énumérer, vous ne pouvez pas faire cela (la loi constitutive générale est comme dans cet exemple, x [i + 1] = x [i] +1, ou x [i + 1] = x [i] << 1 ( changement de gauche).) Sinon, leur n'est pas un moyen de itérer sur des éléments d'une énumération. P> Remarque: la fonction Compute code> sera certainement inlinée, mais sans doute que vous puissiez utiliser
Attribut spécifique du compilateur sous forme
__ forcerinline code> avec msvc ou
__ attribut __ ((__ toujours_inline __)) code> avec gcc ou clang. p> p> p>
La seule portée de la simplification que je vois consiste à éliminer le code de la chaudière en remplaçant par une macro fixe. Cela apaisera le spectateur.
au lieu de tant de si-else si code>, faites-le un
commutateur / case code> comme ci-dessous: p>
#define CASE(TAG) \
case TAG: return memory_manager::instance().add(new mfer::t_value<TAG>())
mfer::i_value* make_empty_value(const mfer::tag tag_)
{
switch(tag_) {
{
CASE(mfer::tag::mwf_ble);
CASE(mfer::tag::mwf_chn);
CASE(mfer::tag::mwf_blk);
//...
default: break;
}
return nullptr;
}
#undef CASE
Avec un peu de modèle, nous pouvons obtenir la fonction d'usine jusqu'à: Code complet ci-dessous. P> La carte génératrice i_value est construite au moment de la compilation, permettant une recherche de temps constante. p> contraintes: p> Les valeurs de l'énum doivent être consécutives, mais elles n'ont pas besoin de commencer à zéro. p> li>
Cette démo nécessite C ++ 14. Il peut être facilement adapté pour travailler avec C ++ 11. Pour C ++ 03, nous voudrions tendre la main pour booster mpl ou boost_pp. P> li>
ul> Exemple de fonctionnement complet: p>
I have tag 0
I have tag 1
tag 1 destroyed
tag 0 destroyed
Puis-je vous demander pourquoi vous avez enveloppé Void () aux fonctions de T_Value? Ça fait mieux?
Croyez-le ou non, l'emballage des opérations OSTREAM en annulation empêche le Xcode de mal former le code. Il s'agit également d'une manière portable d'indiquer que vous ignorez délibérément la valeur de retour.
S'il vous plaît ne postez pas votre code comme une image. Postez-le comme le texte dans la réponse.
Vous pouvez modifier ces
si code> s sur
commutateur / case code> si
mfre :: tag :: mwf _ * code> sont des constantes. Cela peut améliorer la lisibilité.
Pouvez-vous partager la définition de la classe
t_value code>? Au moins les parties pertinentes où
tag_type code> influence la définition de cette classe. C'est tout à fait possible, basé sur ce que vous faites, que
t_value code> ne doit pas être une classe de modèle du tout. Tag_Type pourrait être transmis dans le constructeur.
@Forcebru merci pour votre conseil. Et plus, existe-t-il une solution essentielle pour ce code? Je pense que la conversion de commutation aidera mais elle ne pouvait pas résoudre la complexité essentielle de ce code.
@selbie C'est ma faute mais le partage de codes sera difficile, car ce sera long. Mais il est clair, la classe
t_value code> est fortement liée au tag_type.
Je voudrais utiliser un commutateur
code>