Salutations Tout.
J'écris du code à l'aide de la bibliothèque d'unités de boost et j'ai rencontré un problème. P>
J'ai réussi à résumer le problème du code de boost afin que vous ne cherchiez pas à regarder à travers des ramed of Boost Modèle Meta Programming. Bien que je suis sûr que si vous avez une expérience avec cela, cela pourrait aider. Voici la reproduction: p> donc le problème (spécifiquement) est la suivante: maintenant, toutes les classes autres que J'utilise MSVC ++ 2008 au cas où il est pertinent pour quiconque. P> Modifier: Ajout d'une solution possible (assez probable) dans les réponses forte> p> p> myU * myBase code> utilise
opérateur * (u, const BASE &) CODE> et renvoie le type de
BASE CODE>, tous bien jusqu'à présent. Tandis que
myu * myderived code> insiste sur l'utilisation de
U :: opérateur * (Y) code> et renvoie donc un
q code>, pas bon parce que je voulais un < code> base code> à nouveau. p>
base code> et
dérivé code> sont des classes de bibliothèque de boost afin que je ne puisse pas modifier les membres de U. Comment puis-je "battre"
u :: opérateur * (y) code> pour la déduction / instanciation de la surcharge / du modèle, dans ce cas, dans un élégant et "résolu une fois pour toujours". p>
6 Réponses :
Premièrement, le problème: le paramètre const basé & code> de l'opérateur
code> sera toujours un ajustement pire que le paramètre de modèle du paramètre de modèle en raison de la conversion de
dérivé code> à
base code>.
Ensuite, la solution: fournir un opérateur surchargé * code> pour chaque classe dérivée. : ( p>
@ Xeo: J'ai remarqué cela juste comme je l'ai posté, je l'ai changé en const Base & Code>, ce qui est dans le code réel. Cela n'affecte pas le résultat. J'espère qu'il y a une meilleure solution que l'opérateur * pour chaque classe dérivée.
@Edf: J'appuie au moins connaître de non autre. Même en prenant le paramètre de base comme un pointeur n'a pas aidé, ce que je pensais pourrait ...: /
L'utilisation des éléments suivants doit corriger votre problème au lieu de p> Ce n'est pas ce que nous pouvions appeler une "solution propre" bien que.
J'essaie de trouver une meilleure façon de le faire. P> p>
Le problème évident avec cette approche est la tranchage. Peut-être que @edf a besoin de certaines fonctions virtuelles appelées à travers la référence de base? : /
Cela pourrait le réparer. Cependant, les classes dérivées en question sont utilisées massivement i> et la coulée de chaque fois que chaque fois ne serait pas pratique pour le code de la clientèle (ce qui serait à peine conscient que le dérivé a même une classe de base, grâce à Typefefs).
On dit la vérité que la tranchée n'est pas vraiment un problème. Dérivé ne contient plus de données qu'une base, mais je n'ai jamais pensé que c'est une bonne idée de couper les choses même quand "ça ne pouvait pas faire mal".
@Valka: une distribution à base et code> (note la référence) corrige cependant les problèmes de tranchage. ;)
Si vous avez le contrôle de la commande des opérateurs, vous pouvez définir votre Il ne correspondrait pas au modèle de classe opérateur * code> dans le sens opposé, c'est-à-dire
u code>, vous entourer du numéro de la fonction de modèle dans
u code> primordial votre propre opérateur
code> fonction. p> p>
Le problème est que vous DO B> DO B> DO MYNERVIED * MYU CODE> et
MYBASE * MYU CODE> et ne peut pas changer la commande. Je pense que le problème est que la surcharge fournie par
u code> est toujours meilleure, car aucune réorganisation des paramètres n'est nécessaire.
Tous les opérateurs sont définis à la fois, dans mon code et la bibliothèque. J'ai laissé ces choses pour garder l'exemple aussi concis que possible, car il est déjà massif en ce qui concerne les problèmes de langage élémentaire.
Ok, eh bien, ça valait un coup de poignard si vous veniez de commencer, et n'avez pas eu de base de code étendue à maintenir :)
Apprécié, j'ai déjà passé des journées sur ce problème ... Ce n'est qu'aujourd'hui que j'ai finalement réussi à le reproduire sans les milles de modèle métaprogrammant que cela est intégré. Je me sente certainement plus proche de la solution que cela a été réduit à sa forme actuelle. Espérons que quelqu'un aura une idée de réflexion massive. Le problème est qu'il y a tant de façons de presque i> correctement.
@Edf: Ou réellement le réparer, mais avec une partie de maintenance massive de votre côté pour fournir tout l'opérateur surchargé * code> pour les classes dérivées. : /
Utilisation de sfinae pour C ++ 03 ( une solution alternative de le faire avec C ++ 0x ( Un test rapide indique que votre exemple semble travailler avec Sfinae, mais être averti que les deux opérateurs doivent être des surcharges pour que cela fonctionne: si comme Xeo a souligné, ce qui précède n'aide pas. Es-même que je vous rachene, voici une dernière possibilité: p> dans l'exemple, le membre boost :: is_base_of code> est de boost.typetits):
std :: is_base_of code> est de
opérateur * (Y) code> est le seul opérateur qui apparaît dans le jeu de résolution de surcharge (par exemple à cause de l'ADL ou parce que d'où
opérateur * (u, base const &) code> est déclaré), Sfinae le fera disparaître (comme prévu) mais la résolution de la surcharge finira sans candidat. P>
opérateur * (Y) code> est non-const. Si, cependant, il était constitué comme
opérateur * (y) const code> comme bon style recommande, alors vous avez pourriez em> fournir un meilleur match non-const qui transmet à votre
Opérateur * (u const &, base const &) code>. Ceci est fragile Toutefois: si votre code utilise un
u const & code>, vous trébucherez sur l'erreur de compilation d'origine. P> p>
L'OP a dit qu'il ne peut rien changer d'après la base et les cours dérivés, car cela vient de boost.
problème intéressant. Les modèles et héritage ne se mélangent pas vraiment bien, et puisque vous ne pouvez pas corriger Je propose d'atténuer le mécanisme de déduction de la surcharge :) P> Le moyen le plus simple serait de fournir une surcharge pour chaque classe code> dérivée code>. Évidemment, il est impraticable. P> Sauf si nous pouvions utiliser une classe d'assistance pour laquelle l'opérateur est écrit et mélanger Typefs de là pour le rendre transparent pour le client. P> u code> cela fait un défi intéressant à coup sûr.
struct Base {};
template <typename T>
struct BaseT: Base
{
typedef T Tag;
};
struct DerivedTag {};
typedef BaseT<DerivedTag> Derived;
class Q {};
class U
{
public:
template< typename Y >
Q operator * (Y)
{
Q r;
return r;
}
};
Base operator * (U, const Base &)
{
Base r;
return r;
}
template <typename T>
BaseT<T> operator*(U, BaseT<T> const&) { return BaseT<T>(); }
int main(int argc, char **argv)
{
Base myBase;
U myU;
Base myOtherBase = myU * myBase;
Derived myDerived;
Derived myOtherDerived = myU * myDerived;
return 0;
}
Tout comme j'ai abandonné essayé de résoudre cette dernière nuit, la réponse m'a frappé comme une brique. Le résultat code> q code> de u :: opérateur * (base) code> est conceptuellement identique à la base
base code> résultat tapé de
opérateur * ( U, base) code>, même si elles sont représentées par différents types. Tout ce que j'ai besoin de faire est de fournir un constructeur pour
base (const Q &) code> qui accepte le type Q.
class Base
{
public:
Base(){}
Base(const Q &){}
};
Eh bien, cela résoudra-t-il réellement le problème? C'était en fait l'une de mes premières pensées, mais je pensais que vous ne pouviez pas faire de construction utile de ce q code>. Si cela fonctionne, alors félicitations. :)
+1 pour un code d'exemple autonome autonome. :)
Qu'est-ce qui vous est venu à l'esprit: Est-ce que le boost
u code> classe utilise Sfinae sur l'opérateur?
Et vous venez d'apprendre que malheureusement l'héritage et le modèle ne se mélangent pas bien: /
@Matthieu: Ce n'est certainement pas vrai. Ils se mélangent très bien, car ils résolvent des problèmes orthogonaux. Les combinaisons de métaprogramming de compilation et i> le polymorphisme d'exécution peuvent construire un excellent code.
@Alexandre C: Je suis d'accord, vous pouvez résoudre un excellent problème, mais avoir des classes de base et des arguments de modèle dans différentes surcharges et les amener à agir comme vous le souhaitez peut conduire à beaucoup de gratter. Il existe bien sûr des solutions, mais certainement pas aussi immédiat que l'on pouvait penser, à juste titre à cause de l'orthogonalité des approches :) Je pense avoir résolu celui-ci sans trop de problèmes, mais toujours, cela a pris plusieurs jours pour personnaliser Sortir l'exemple minimal: /