Contenu | Rechercher | Menus

Annonce

Ubuntu 16.04 LTS
Commandez vos DVD et clés USB Ubuntu-fr !

Pour en savoir un peu plus sur l'équipe du forum.

Si vous avez des soucis pour rester connecté, déconnectez-vous puis reconnectez-vous depuis ce lien en cochant la case
Me connecter automatiquement lors de mes prochaines visites.

#1 Le 13/11/2017, à 19:43

Destroyers

[C++] Une méthode template ne peut pas être virtuelle ...

Bonjour à tous,

J'écris un module de manipulation de temps.
J'ai une classe Timer, représentant une durée écoulée depuis un certain moment :

class Timer
{
public:

  template<typename ratio, typename IntegerReturnType = unsigned>
  IntegerReturnType get() const
  {
       return static_cast<IntegerReturnType>(getDuration<std::chrono::duration<unsigned long long, ratio>>().count());
  }

//autres méthodes et attributs
}

Cette méthode get() retourne donc cette durée. le type ratio est un std::ratio et permet de savoir quelle unité on veut (millisecondes ? micro ? nano ?), et le type IntegerReturnType permet de savoir ce que l'on veut retourner (car si on demande des nanosecondes, il vaut mieux retourner un long plutôt qu'un int).

J'ai une seconde classe Countdown qui représente un décompte, un temps restant avant un certain moment. Cette classe possède la même méthode get() avec les mêmes paramètres templates.


PROBLÈME 1 :

J’aimerais coder une fonction sleep qui prendrait l'une de ces deux classes et qui sleeperait durant la durée retournée par get(). Quoi de plus normal que de vouloir fournir une interface commune à Timer et Countdown ? (Surtout que get() n'est pas la seule méthode que ces deux classes ont en commun). Malheureusement, get() est une méthode template et ne peut donc pas être virtuelle ! (Je sais le pourquoi du comment ne vous affolez pas ^^).

Au lieu d'utiliser le polymorphisme dynamique, j'ai donc dû utiliser le polymorphisme statique :

template<typename T>
void sleep(T const& objet)
{
  std::this_thread::sleep_for(objet.get<std::milli>());
}

Ça marche mais ne trouve pas ça franchement élégant. N'y a-t-il vraiment aucun moyen de faire un arbre d'héritage et utiliser le vrai polymorphisme ?


PROBLÈME 2 :

Cela m'amène à mon 2eme problème (qui est en fait le vrai problème) :

J'aimerais maintenant coder une classe RelativeTimer, qui hérite de Timer, et qui possède une vitesse relativiste, et donc le temps s'y écoule différement. J'aimerais alors spécialiser la méthode get() pour multiplier le temps écoulé par le facteur de Lorentz (j'épargne les détails). Malheureusement, c'est une chose qui semble impossible puisque encore une fois get() est template et ne peut donc pas être virtuelle ! Et là je ne trouve aucune alternative.

J'ai évidement effectué quelques recherches, la plupart des solutions semblent converger vers ce que l'on nomme le "Type erasure"... Malheureusement je n'ai pas l'impression que cela soit la solution à mon problème (ou alors peut être que je n'ai pas bien compris les articles que j'ai lu sur le sujet).


PROBLÈME 3 :

Bon ici ce n'est pas un problème, c'est une question subsidiaire.
Soit la fonction suivante :

Template<typename T>
void foo(T var)
{
//do something
}

A quoi sert une spécialisation totale ? Une simple surcharge ne remplie-t-elle pas le même rôle ?
Les deux codes suivants ne sont ils pas exactement identiques ?

Template<>
void foo<int>(int var)
{
//do something
}
void foo(int var)
{
//do something
}

Merci pour le temps passé sur ce poste smile

Dernière modification par Destroyers (Le 13/11/2017, à 19:47)

Hors ligne

#2 Le 13/11/2017, à 22:33

grigouille

Re : [C++] Une méthode template ne peut pas être virtuelle ...

Problème 3 : tu peux aussi écrire :

template<> void foo(int var){...}

Cela indique que c'est une spécialisation de foo<T>.

Voici la réponse à ta question :

$ cat toto.cpp
#include <iostream>
using std::cout;
template<class T> void foo(T a) {
	cout << "Dans T\n";
}
template<> void foo(int a) {
	cout << "Dans int <>\n";
}
void foo(int a) {
	cout << "Dans int \n";
}
int main() {
	foo(1.0);
	foo<>(1);
	foo(1);
}
$ g++ -o toto toto.cpp
$ ./toto
Dans T
Dans int <>
Dans int 

Xubuntu 16.04

Hors ligne

#3 Le 14/11/2017, à 08:20

grigouille

Re : [C++] Une méthode template ne peut pas être virtuelle ...

Pour la méthode get, je te suggère :
- soit de remonter le template au niveau de la class
- soit de créer des méthodes get non template (en plus de la version template) qui, elles, pourront être virtuelles.


Xubuntu 16.04

Hors ligne