Précédent   Forum des professionnels en informatique > C et C++ > C++
C++ Forum d'entraide technique sur le langage C++. Avant de poster -> F.A.Q C++
Partagez cette discussion sur d'autres réseaux sociaux : Viadeo Twitter Google Facebook Digg Delicious MySpace Yahoo
Réponse Proposer ce sujet en actualité
 
Outils de la discussion
Publicité
'
Vieux 27/01/2012, 11h40   #1
Membre expérimenté
 
Inscription : février 2004
Messages : 1 301
Détails du profil
Informations forums :
Inscription : février 2004
Messages : 1 301
Points : 528
Points : 528
Envoyer un message via MSN à mister3957
Par défaut Invoquer un template d'enum

Bonjour à tous,

J'ai deux enums comme ceci :
Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
enum E_COL
{
   E_COL_0,
   E_COL_1,
   E_COL_2;
   E_COL_COUNT
};
 
enum E_ROW
{
   E_ROW_0,
   E_ROW_1,
   E_ROW_2;
   E_ROW_COUNT
};
Ainsi qu'une classe template comme ceci :
Code :
1
2
3
4
5
6
template<E_COL COL, E_ROW ROW>
class CColRowHelper
{
	enum { activated = false };
        static void DoSomething() {}
};
Lorsque je veux activer un point, il me faut spécialiser cette classe template. Par exemple, la colonne 1 avec la row 2 :
Code :
1
2
3
4
5
template<> CColRowHelper<E_COL_1, E_ROW_2>
{
	enum { activated = true };
        static void DoSomething() { /* it does something */ }
};
A l'initialisation, toute association colonne / row étant marquée comme "activée", il faut que j'exécute la méthode "DoSomething()"

Pour le moment, je ne vois qu'une solution, mais pas mal contraignante, qui serait de répertorier toutes les associations possibles :
Code :
1
2
3
4
5
if(CColRowHelper<E_COL_0, E_ROW_0>::activated)
    CColRowHelper<E_COL_0, E_ROW_0>::DoSomething()
 
if(CColRowHelper<E_COL_0, E_ROW_1>::activated)
    CColRowHelper<E_COL_0, E_ROW_1>::DoSomething()
N'y aurait-il pas un moyen de faire quelque chose de ce style ? :
Code :
1
2
3
4
for(int col = 0; col < E_COL_COUNT; ++col)
    for(int row = 0; row < E_ROW_COUNT; ++row)
        if(CColRowHelper<col, row>::activated)
            CColRowHelper<col, row>::DoSomething();
Merci à vous,
A bientôt
__________________
"Heureusement qu'il y avait mon nez, sinon je l'aurais pris en pleine gueule" Walter Spanghero
mister3957 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 27/01/2012, 12h16   #2
Membre Expert
 
Homme
Junior developer C/C++/Embedded system
Inscription : juin 2010
Messages : 656
Détails du profil
Informations personnelles :
Sexe : Homme
Localisation : France

Informations professionnelles :
Activité : Junior developer C/C++/Embedded system

Informations forums :
Inscription : juin 2010
Messages : 656
Points : 1 371
Points : 1 371
Bonjour,

pourquoi ne pas utiliser un simple tableau ?

Code :
1
2
3
4
5
6
7
8
9
10
11
class CColRowHelper
{
public:
	bool activated;
        static void DoSomething() {}
};
CColRowHelper* ColRowTab[E_COL_COUNT*E_ROW_COUNT];
CColRowHelper* GetColRow(E_COL col, E_ROW row)
{
   return ColRowTable[col*E_COL_COUNT+row];
}
Après tu es libre de bidouiller des fonctions autour de ça.
Bousk est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 27/01/2012, 12h26   #3
Membre expérimenté
 
Homme Léo Gaspard
Lycéen
Inscription : janvier 2012
Messages : 342
Détails du profil
Informations personnelles :
Nom : Homme Léo Gaspard
Localisation : France

Informations professionnelles :
Activité : Lycéen

Informations forums :
Inscription : janvier 2012
Messages : 342
Points : 575
Points : 575
Les templates sont évaluées à la compilation, le for à l'exécution.
Mais il est possible de passer outre : https://github.com/Ekleog/misc/blob/master/tplfor.cpp
Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
 
template <int Col, int RFrom, int RTo, template <int, int> class Call>
struct ForRow {
    static void run() {
        Call<Col, RFrom>::run();
        ForRow<Col, RFrom + 1, RTo, Call>::run();
    }
};
template <int Col, int REnded, template <int, int> class Call>
struct ForRow<Col, REnded, REnded, Call> {
    static void run() { }
};
 
template <int CFrom, int CTo, int RFrom, int RTo, template <int, int> class Call>
struct For {
    static void run() {
        ForRow<CFrom, RFrom, RTo, Call>::run();
        For<CFrom + 1, CTo, RFrom, RTo, Call>::run();
    }
};
template <int CEnded, int RFrom, int RTo, template <int, int> class Call>
struct For<CEnded, CEnded, RFrom, RTo, Call> {
    static void run() { }
};
 
// Pour tester la compilation
#include <cstdio>
template <int Col, int Row> struct CColRowHelper {
    enum { activated = true };
    static void DoSomething() { std::printf("."); }
};
template <> struct CColRowHelper<5, 5> {
    enum { activated = false };
    static void DoSomething() { }
};
 
// Le foncteur
template <int Col, int Row>
struct IfActDoSth {
    static void run() {
        if (CColRowHelper<Col, Row>::activated)
            CColRowHelper<Col, Row>::DoSomething();
    }
};
 
// Et l'appel
void DoTheSths() {
    For<0, 10, 0, 10, IfActDoSth>::run();
    // Lance IfActDoSth::run() pour 0,1,2,3,4,5,6,7,8,9 en ligne et idem pour
    // les colonnes.
}
 
// Un main de test
int main(int, char**) {
    DoTheSths();
}
Au passage, si tu définis CColRowHelper comme tu nous l'as annoncé, alors le test de if (...::activated) est inutile : dans le cas contraire, DoSomething ne fait rien.
Ekleog est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 07/02/2012, 17h23   #4
Membre expérimenté
 
Inscription : février 2004
Messages : 1 301
Détails du profil
Informations forums :
Inscription : février 2004
Messages : 1 301
Points : 528
Points : 528
Envoyer un message via MSN à mister3957
Citation:
Envoyé par Ekleog Voir le message
Au passage, si tu définis CColRowHelper comme tu nous l'as annoncé, alors le test de if (...::activated) est inutile : dans le cas contraire, DoSomething ne fait rien.
Merci Ekleog, j'ai fait comme ça et ça fonctionne bien

En revanche, le test de "if (CColRowHelper<Col, Row>::activated)" à la ligne 41 qui est définit dans le foncteur, serait-il possible de le déplacer dans l'enchaînement des templates ?

Etant donné que c'est connu à la compilation, autant le gérer à la compilation non ?

C'est pas grand chose mais ce test va être exécuté des milliards de fois, alors j'imagine que ça aura un bon impact se l'ensemble..

Merci encore
__________________
"Heureusement qu'il y avait mon nez, sinon je l'aurais pris en pleine gueule" Walter Spanghero
mister3957 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 07/02/2012, 19h13   #5
Membre expérimenté
 
Homme Léo Gaspard
Lycéen
Inscription : janvier 2012
Messages : 342
Détails du profil
Informations personnelles :
Nom : Homme Léo Gaspard
Localisation : France

Informations professionnelles :
Activité : Lycéen

Informations forums :
Inscription : janvier 2012
Messages : 342
Points : 575
Points : 575
Même exécuté des milliards de fois, un compilateur sera toujours assez intelligent pour optimiser ... Parce qu'un if(1) goto a; else goto b; ce n'est pas trop dur à optimiser, hein. Surtout vu qu'il n'y a même pas de else !
Enfin, sauf peut-être si tu donnes -O0 !

EDIT : Petit test (en C pour rendre l'assembleur plus compréhensible, mais c'est tout pareil en C++) avec -O[0, 1, 2, 3] :
Code :
1
2
3
4
5
6
7
8
9
#include <stdio.h>
int main() {
  if (1) {
    printf("1");
  } else {
    printf("0");
  }
  return 0;
}
Résultats :

D'abord, une remarque : -O2 et -O3 donnent les mêmes résultats.

Maintenant, le désassemblage (je ne me préoccupe que du main) :
Code :
1
2
3
4
5
6
7
8
// -O0
   0x00000000004004e4 <+0>:     push   rbp
   0x00000000004004e5 <+1>:     mov    rbp,rsp
   0x00000000004004e8 <+4>:     mov    edi,0x31
   0x00000000004004ed <+9>:     call   0x4003e0 <putchar@plt>
   0x00000000004004f2 <+14>:    mov    eax,0x0
   0x00000000004004f7 <+19>:    pop    rbp
   0x00000000004004f8 <+20>:    ret
Code :
1
2
3
4
5
6
7
// -O1
   0x00000000004004e4 <+0>:     sub    rsp,0x8
   0x00000000004004e8 <+4>:     mov    edi,0x31
   0x00000000004004ed <+9>:     call   0x4003e0 <putchar@plt>
   0x00000000004004f2 <+14>:    mov    eax,0x0
   0x00000000004004f7 <+19>:    add    rsp,0x8
   0x00000000004004fb <+23>:    ret
Code :
1
2
3
4
5
6
7
// -O2 (= -O3)
   0x0000000000400400 <+0>:     sub    rsp,0x8
   0x0000000000400404 <+4>:     mov    edi,0x31
   0x0000000000400409 <+9>:     call   0x4003e0 <putchar@plt>
   0x000000000040040e <+14>:    xor    eax,eax
   0x0000000000400410 <+16>:    add    rsp,0x8
   0x0000000000400414 <+20>:    ret
Il reste quelques différences, mais un point commun est décelable : à aucun niveau il n'y a de saut (aucune instruction j**).

Donc, même avec -O0, l'optimisation se fait !
Ekleog est déconnecté   Envoyer un message privé Réponse avec citation 00
Réponse Proposer ce sujet en actualité
Outils de la discussion



Fuseau horaire GMT +2. Il est actuellement 20h51.


 
 
 
 
Partenaires

Hébergement Web