Je voudrais avoir dans ma bibliothèque un modèle de fonction func
tel que l'utilisateur peut le surcharger avec ses propres types. Le problème est que mon système de type est de la formeModèle récurrence mutuelle
T := A<T>, B<T>, C
En tant que tel, template<class T> void func(A<T>);
besoins template<class T> void func(B<T>);
si elle est spécialisée avec T = B<C>
. Réciproquement, si nous instancions func(B<T>)
avec T = A<C>
, la spécialisation B<T>
nécessite la spécialisation A<T>
.
Le problème jusqu'à ici pourrait être résolu en déclarant le modèle fonctionne dans un en-tête commun.
Ce que je ne sais pas comment aborder est de savoir comment rendre ce système de type extensible. Je voudrais que l'utilisateur puisse définir son propre type template<class T> class D<T>;
et implémenter son propre template<class T> void func(D<T>);
. Dans ce cas, je ne sais pas comment l'utilisateur pourrait transmettre son type de sorte que dans la spécialisation A<D<C>>
la fonction void func(A<T>);
est capable de trouver void func(D<T>);
.
Y a-t-il un moyen standard de le faire?
Modifier minimal exemple de travail du problème:
// dans A.hpp
namespace ns {
template<class T> struct A { T t; };
template<class T>
void fun (A<T> a) { fun(a.t); }
}
// B.hpp
namespace ns {
template<class T> struct B { T t; };
template<class T>
void fun (B<T> b) { fun(b.t); }
// C.hpp
#include <iostream>
namespace other {
template<class T>
struct C {};
}
namespace ns {
template<class T>
void fun(other::C<T> c) { std::cout << "C" << std::endl; }
}
// main.cpp
#include "A.hpp"
#include "B.hpp"
#include "C.hpp"
namespace ns {
void f() {
fun(A<B<other::C<int>>>());
}
}
int main() {
ns::f();
}
Cet exemple ne compile pas. Il compile si nous réordonner les inclut dans main.cpp
comme
#include "C.hpp"
#include "B.hpp"
#include "A.hpp"
Maintenant, cela est clairement un hack. Avec cette conception, l'utilisateur ne pourra pas instancier à la fois A<B<C<int>>>
et B<A<C<int>>>
. Une solution à cela serait de transmettre les déclarations A
et B
dans un autre modèle et de l'inclure à la fois dans A.hpp
et B.hpp
. Le problème vient maintenant lorsque vous essayez de laisser l'utilisateur de la bibliothèque définir ses propres types. Si l'utilisateur de la bibliothèque définit son propre type template<class T> class D;
, elle ne peut pas transmettre la déclaration, et si elle tente d'instancier A<D<C<int>>>
, la compilation échouera.
Dans cet exemple, l'espace de noms other
représente un espace de noms sur lequel je n'ai aucun contrôle et C
représente une classe préexistante dans une autre bibliothèque. Cela peut être considéré comme une classe boost
ou similaire. L'espace de noms ns
est celui que ma bibliothèque définit.
S'il vous plaît montrer un code réel. –
Je pourrais deviner ce que vous entendez par "de la forme", mais je pourrais facilement me tromper. Le code réel qui dessine l'idée élimine une grande partie de cette ambiguïté. 'T: = A' est à tout le moins abuser d'un T réutilisant pour signifier deux choses différentes sur la même déclaration, et je suis incertain si cette virgule indique une étrange récusion ou ce n'est qu'une liste de ce que 'T' peut être. Code réel en éditant la question démontrant votre plan s'il vous plaît (ce code devrait compiler) –
Yakk
Par ': =' Je voulais définir une grammaire sur le terme 'T'. J'essaye de reproduire ce comportement dans un court exemple, où la compilation de code dépend de l'ordre des inclusions. – Lezkus