C ++, programmation générique et des fonctions virtuelles. Comment puis-je obtenir ce que je veux?
-
01-10-2019 - |
Question
est ce que je voudrais faire en utilisant des modèles:
struct op1
{
virtual void Method1() = 0;
}
...
struct opN
{
virtual void MethodN() = 0;
}
struct test : op1, op2, op3, op4
{
virtual void Method1(){/*do work1*/};
virtual void Method2(){/*do work2*/};
virtual void Method3(){/*do work3*/};
virtual void Method4(){/*do work4*/};
}
Je voudrais avoir une classe qui dérive tout simplement d'une classe de modèle qui fournit ces déclarations de méthode tout en même temps en les rendant virtuel. Voilà ce que j'ai réussi à trouver:
#include <iostream>
template< size_t N >
struct ops : ops< N - 1 >
{
protected:
virtual void DoStuff(){ std::cout<<N<<std::endl; };
public:
template< size_t i >
void Method()
{ if( i < N ) ops<i>::DoStuff(); }
//leaving out compile time asserts for brevity
};
template<>
struct ops<0>
{
};
struct test : ops<6>
{
};
int main( int argc, char ** argv )
{
test obj;
obj.Method<3>(); //prints 3
return 0;
}
Cependant, comme vous l'avez probablement deviné, je suis incapable de passer outre l'une des 6 méthodes que j'ai hérité. Je suis évidemment manque quelque chose ici. Quelle est mon erreur? Non, ce n'est pas devoirs. Ceci est la curiosité.
La solution
Testé avec GCC 4.3. Ne sais même pas pourquoi j'ai passé du temps à ce sujet: - /
#include <iostream>
template <std::size_t N>
struct mark
{ };
template <std::size_t N>
struct op : op <N - 1>
{
virtual void do_method (const mark <N>&) = 0;
};
template <>
struct op <1>
{
virtual void do_method (const mark <1>&) = 0;
};
struct test : op <2>
{
template <std::size_t K>
void
method ()
{ do_method (mark <K> ()); }
virtual void do_method (const mark <1>&)
{ std::cout << "1\n"; }
virtual void do_method (const mark <2>&)
{ std::cout << "2\n"; }
};
int
main ()
{
test x;
x.method <1> ();
x.method <2> ();
}
Je ne sais pas comment déplacer la fonction de modèle de method()
« de prettifier » sur test
.
Autres conseils
template< size_t N >
struct ops : ops< N - 1 >
Ce code une boucle sans fin. La récursion ne s'arrête pas lorsque N atteint 0. Ajouter une spécialisation dans le cas final, immédiatement après le modèle principal:
template<>
struct ops<0> {}
En outre, qu'est-ce que cela fait? Pourquoi ne pas simplement appeler directement ops<i>::DoStuff()
?
template< size_t i >
void Method()
{ if( i < N ) ops<i>::DoStuff(); }
Pour votre désir mimétique d'origine:
#define MAKE_OPS(N) template<> struct Ops<N> : Ops<N-1> { virtual void Method##N() = 0; }
template<int N>
struct Ops;
template<>
struct Ops<0> { };
MAKE_OPS(1);
MAKE_OPS(2);
template<> struct Ops<3> : Ops<2> { virtual void Method3() { std::cout << "3" << std::endl; } };
MAKE_OPS(4);
MAKE_OPS(5);
MAKE_OPS(6);
struct Test : Ops<3> {
virtual void Method1() { std::cout << 1 << std::endl; }
virtual void Method2() { std::cout << 2 << std::endl; }
};