IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

C++ Discussion :

constructeur, destructeur ou conversion de type attendue. c'est quoi cette erreur?


Sujet :

C++

  1. #1
    Membre averti
    Homme Profil pro
    Game Graphics Programmer
    Inscrit en
    Août 2006
    Messages
    408
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Allemagne

    Informations professionnelles :
    Activité : Game Graphics Programmer
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Août 2006
    Messages : 408
    Points : 392
    Points
    392
    Par défaut constructeur, destructeur ou conversion de type attendue. c'est quoi cette erreur?
    Bonjour,
    dans le code ci-dessous, j'obtiens 2 fois la même erreur de compilation disant "error: expected constructor, destructor or type conversion before 'kazu'".
    Je n'arrive pas à m'expliquer cette erreur, ni de quoi elle résulte, ni comment la résoudre. J'espère qu'une âme éclairée et châritable arrive à me l'expliquer, voire à la corriger.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
     
    #include <iostream>
     
    namespace kazu 
    {
    	//forward declarations
    	namespace base 
    	{
    		template<typename T, unsigned int L>
    		struct	vecN;
     
    		template<typename T, unsigned int L>
    		struct	vecD;
    	}
     
    	namespace math
    	{
    		template<
    		typename T,
    		unsigned int L,
    		typename V = kazu::base::vecD<T, L>
    		>
    		struct	vecmath;
    	}
     
     
    	//typedefs
    	template<typename T>
    	struct blast
    	{		
    		typedef base::vecD<T, 2> vec2;
    		typedef base::vecD<T, 3> vec3;
    		typedef base::vecD<T, 4> vec4;
     
     
    	};
    }
     
    namespace kazu
    {
    	namespace base 
    	{
    		template<typename T>
    		struct	vecD<T, 2> : kazu::math::vecmath<T, 2>
    		{
    			union
    			{
    				T	_v[2];
    				struct	{ T x, y;};
    				struct	{ T s, t;};
    				struct	{ T i, a;};
    			};
    			vecD(const T v[2]): x(v[0]), y(v[1]) {}
    			vecD(T x_ = (T)0, T y_ = (T)0): x(x_), y(y_)	{}
    			vecD(const vecD& ref): x(ref.x), y(ref.y) {}
    		};
     
    		template<typename T>
    		struct	vecD<T, 3> : kazu::math::vecmath<T, 3>
    		{
    			union
    			{
    				T	_v[3];
    				struct	{ T x, y, z;};
    				struct	{ T s, t, p;};
    				struct	{ T r, g, b;};
    			};
    			vecD(const T v[3]): x(v[0]), y(v[1]), z(v[2]) {}
    			vecD(T x_ = (T)0, T y_ = (T)0, T z_ = (T)0): x(x_), y(y_), z(z_)	{}
    			vecD(const vecD& ref): x(ref.x), y(ref.y), z(ref.z) {}			
    		};
     
    		template<typename T>
    		struct	vecD<T, 4> : kazu::math::vecmath<T, 4>
    		{
    			union
    			{
    				T	_v[4];
    				struct	{ T x, y, z, w;};
    				struct	{ T s, t, p, q;};
    				struct	{ T r, g, b, a;};
    			};
    			vecD(const T v[4]): x(v[0]), y(v[1]), z(v[2]), w(v[3]) {}
    			vecD(T x_ = (T)0, T y_ = (T)0, T z_ = (T)0, T w_ = (T)0): x(x_), y(y_), z(z_), w(w_)	{}
    			vecD(const vecD& ref): x(ref.x), y(ref.y), z(ref.z), w(ref.w) {}			
    		};
     
    		template<typename T, unsigned int L>
    		struct vecN : 
    			vecD<T, L>,
    		kazu::math::vecmath<T, L>
    		{			
    		};
     
    	}
     
    	namespace math
    	{
    		template<
    			typename T,
    			unsigned int L,
    			typename V
    		>
    		struct	vecmath
    		{
    			typedef	T	scalar_type;
    			typedef V	vector_type;
    			enum		{ vector_length = L };
     
    			static V cross(const V& rhv, const V& lhv);
     
    			static T dot(const V& rhv, const V& lhv);			
    			static V lerp(const V& rhv, const V& lhv, float t);
     
    		};		
    	}
    }
     
    using namespace kazu;
     
     
    template<typename T>
    kazu::math::vecmath<T, 2>::vector_type
    kazu::math::vecmath<T, 2>::cross( //erreur ici
    kazu::math::vecmath<T, 2>::vector_type& rhv,
    kazu::math::vecmath<T, 2>::vector_type& lhv)
    {
     
    	//impl
    	return kazu::math::vecmath<T, 2>::vector_type(rhv.x* lhv.y, rhv.y * lhv.x);
    }
     
     
    template<typename T>
    kazu::math::vecmath<T, 2>::scalar_type
    kazu::math::vecmath<T, 2>::dot( //erreur ici
    kazu::math::vecmath<T, 2>::vector_type& rhv,
    kazu::math::vecmath<T, 2>::vector_type& lhv)
    {
     
    	//impl
    	return kazu::math::vecmath<T, 2>::value_type(0);
    }
     
     
     
    int main (int argc, char * const argv[]) 
    {
    	//using kazu::blast<float>;
     
    	kazu::blast<float>::vec2 a2;
    	kazu::blast<float>::vec2 b2;
    	kazu::blast<float>::vec2 c2(kazu::blast<float>::vec2::cross(a2, b2));
    	float dot2 = kazu::blast<float>::vec2::dot(a2, c2);
     
    	kazu::blast<float>::vec3 a3;
    	kazu::blast<float>::vec3 b3;
    	kazu::blast<float>::vec3 c3(kazu::blast<float>::vec3::cross(a3, b3));
    	float dot3 = kazu::blast<float>::vec3::dot(a3, c3);
     
     
     
        // insert code here...
        std::cout << "Hello, World!\n" << dot2 << dot3;
        return 0;
    }
    Notez que je compile avec GCC 4.x de Xcode 3.1 sous MacOSX 10.5.6.
    A quoi cette erreur est-elle due?
    Comment la résoudre ou la contourner?

  2. #2
    Rédacteur
    Avatar de Laurent Gomila
    Profil pro
    Développeur informatique
    Inscrit en
    Avril 2003
    Messages
    10 651
    Détails du profil
    Informations personnelles :
    Âge : 39
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Avril 2003
    Messages : 10 651
    Points : 15 920
    Points
    15 920
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    typename kazu::math::vecmath<T, 2>::vector_type
    ...
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    typename kazu::math::vecmath<T, 2>::scalar_type
    ...

  3. #3
    Expert confirmé
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Décembre 2003
    Messages
    3 549
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Décembre 2003
    Messages : 3 549
    Points : 4 625
    Points
    4 625
    Par défaut
    Il manque des typename dans plein d'endroits.
    C'est fou comment les gens peuvent avoir du mal avec cette règle toute simple...
    Boost ftw

  4. #4
    Membre éclairé Avatar de HanLee
    Profil pro
    Inscrit en
    Mai 2004
    Messages
    738
    Détails du profil
    Informations personnelles :
    Âge : 37
    Localisation : France, Rhône (Rhône Alpes)

    Informations forums :
    Inscription : Mai 2004
    Messages : 738
    Points : 871
    Points
    871
    Par défaut
    Une somme de règles simples ne fait pas un langage simple !

  5. #5
    Membre averti
    Homme Profil pro
    Game Graphics Programmer
    Inscrit en
    Août 2006
    Messages
    408
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Allemagne

    Informations professionnelles :
    Activité : Game Graphics Programmer
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Août 2006
    Messages : 408
    Points : 392
    Points
    392
    Par défaut
    sachant que ce sont les 2 défintions de fonctions qui sont erronnées, quelle serait la facon correcte de les écrire?

    (Puis c'est quoi la règle toute simple derrière les typename?)

    J'ai essayé dans tous les sens, mais j'obtiens d'autres erreurs du coup, donc j'aimerais savoir quel est la facon correcte de faire ce que je tente ici.

  6. #6
    Expert confirmé
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Décembre 2003
    Messages
    3 549
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Décembre 2003
    Messages : 3 549
    Points : 4 625
    Points
    4 625
    Par défaut
    Si T est un type qui dépend d'un paramètre template, et que T::foo est un type et non une variable, il faut écrire typename T::foo.
    Boost ftw

  7. #7
    Membre expérimenté
    Profil pro
    Inscrit en
    Février 2004
    Messages
    1 824
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2004
    Messages : 1 824
    Points : 1 544
    Points
    1 544
    Par défaut
    Ca permet d'éviter des ambiguïté entre la "templarité" et le signe "inférieur à" <

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    template<class i, int j>
    class T
    {
        typedef i<j> value_type; // i<j> ou i < j avec erreur sur le '>' ?
    };
    J'ai jamais vu l'erreur concrètement
    "Heureusement qu'il y avait mon nez, sinon je l'aurais pris en pleine gueule" Walter Spanghero

  8. #8
    Membre averti
    Homme Profil pro
    Game Graphics Programmer
    Inscrit en
    Août 2006
    Messages
    408
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Allemagne

    Informations professionnelles :
    Activité : Game Graphics Programmer
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Août 2006
    Messages : 408
    Points : 392
    Points
    392
    Par défaut
    En fait, je me demandais, cette partie qui génère des erreurs
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    template<typename T>
    kazu::math::vecmath<T, 2>::scalar_type
    kazu::math::vecmath<T, 2>::dot( //erreur ici
    kazu::math::vecmath<T, 2>::vector_type& rhv,
    kazu::math::vecmath<T, 2>::vector_type& lhv)
    {
     
    	//impl
    	return kazu::math::vecmath<T, 2>::value_type(0);
    }
    ce serait-pas une spécialisation partielle d'une fonction templatisée? A ce moment, ca ne m'étonnerait pas que ca soit fautif en fait... (je tombe assez souvent dans ce piège).

  9. #9
    Expert confirmé
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Décembre 2003
    Messages
    3 549
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Décembre 2003
    Messages : 3 549
    Points : 4 625
    Points
    4 625
    Par défaut
    L'erreur, comme il a été dit vingt fois, c'est que le compilateur considère que
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    kazu::math::vecmath<T, 2>::scalar_type
    désigne une variable et non un type, puisque que c'est ce que dit le standard.

    Or le type de retour d'un prototype de fonction doit être un type. Tu as une variable là où un type est attendu. Bref c'est pas grammaticalement correct.

    Il faut donc écrire

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    template<typename T>
    typename kazu::math::vecmath<T, 2>::scalar_type
    kazu::math::vecmath<T, 2>::dot(
    typename kazu::math::vecmath<T, 2>::vector_type& rhv,
    typename kazu::math::vecmath<T, 2>::vector_type& lhv)
    {
     
    	//impl
    	return typename kazu::math::vecmath<T, 2>::value_type(0);
    }
    Boost ftw

  10. #10
    Membre averti
    Homme Profil pro
    Game Graphics Programmer
    Inscrit en
    Août 2006
    Messages
    408
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Allemagne

    Informations professionnelles :
    Activité : Game Graphics Programmer
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Août 2006
    Messages : 408
    Points : 392
    Points
    392
    Par défaut
    C'est bien ce que j'avais mis. Mais maintenant, j'ai d'autres erreurs.
    - invalid use of undefined type 'struct kazu::math::vecmath<T, 2u>'
    - template definition of non-template 'template<typename T> typename kazu::math::vecmath<T, 2>::vector_type kazu::math::vecmath<T, 2>::cross(typename kazu::math::vecmath<T, 2>::vector_type& rhv, typename kazu::math::vecmath<T, 2>::vector_type& lhv) '
    - declaration of 'struct vecmath<T, 2u>'

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    #include <iostream>
     
    namespace kazu 
    {
    	//forward declarations
    	namespace base 
    	{
    		template<typename T, unsigned int L>
    		struct	vecN;
     
    		template<typename T, unsigned int L>
    		struct	vecD;
    	}
     
    /*	namespace math
    	{
    		template<
    		typename T,
    		unsigned int L
    		//,		typename V = kazu::base::vecD<T, L>
    		>
    		struct	vecmath;
    	}
    */	
     
    	namespace math
    	{
    		template<
    		typename T,
    		unsigned int L
    		//,			typename V
    		>
    		struct	vecmath
    		{
    			typedef	T	scalar_type;
    			//typedef V	vector_type;
    			typedef kazu::base::vecD<T, L>	vector_type;
     
    			enum	{	vector_length = L	};
     
    			static vector_type cross(const vector_type& rhv, const vector_type& lhv);
     
    			static scalar_type dot(const vector_type& rhv, const vector_type& lhv);			
    			static vector_type lerp(const vector_type& rhv, const vector_type& lhv, float t);
     
    		};		
    	}
     
    	//typedefs
    	template<typename T>
    	struct blast
    	{		
    		typedef typename base::vecD<T, 2> vec2;
    		typedef typename base::vecD<T, 3> vec3;
    		typedef typename base::vecD<T, 4> vec4;
     
     
    	};
    }
     
    //definitions
    namespace kazu
    {
    	namespace base 
    	{
    		template<typename T>
    		struct	vecD<T, 2> : kazu::math::vecmath<T, 2>
    		{
    			union
    			{
    				T	_v[2];
    				struct	{ T x, y;};
    				struct	{ T s, t;};
    				struct	{ T i, a;};
    			};
    			vecD(const T v[2]): x(v[0]), y(v[1]) {}
    			vecD(T x_ = (T)0, T y_ = (T)0): x(x_), y(y_)	{}
    			vecD(const vecD& ref): x(ref.x), y(ref.y) {}
    		};
     
    		template<typename T>
    		struct	vecD<T, 3> : kazu::math::vecmath<T, 3>
    		{
    			union
    			{
    				T	_v[3];
    				struct	{ T x, y, z;};
    				struct	{ T s, t, p;};
    				struct	{ T r, g, b;};
    			};
    			vecD(const T v[3]): x(v[0]), y(v[1]), z(v[2]) {}
    			vecD(T x_ = (T)0, T y_ = (T)0, T z_ = (T)0): x(x_), y(y_), z(z_)	{}
    			vecD(const vecD& ref): x(ref.x), y(ref.y), z(ref.z) {}			
    		};
     
    		template<typename T>
    		struct	vecD<T, 4> : kazu::math::vecmath<T, 4>
    		{
    			union
    			{
    				T	_v[4];
    				struct	{ T x, y, z, w;};
    				struct	{ T s, t, p, q;};
    				struct	{ T r, g, b, a;};
    			};
    			vecD(const T v[4]): x(v[0]), y(v[1]), z(v[2]), w(v[3]) {}
    			vecD(T x_ = (T)0, T y_ = (T)0, T z_ = (T)0, T w_ = (T)0): x(x_), y(y_), z(z_), w(w_)	{}
    			vecD(const vecD& ref): x(ref.x), y(ref.y), z(ref.z), w(ref.w) {}			
    		};		
    	}
     
     
    }
     
    using namespace kazu;
     
    #define V_type(n) typename kazu::math::vecmath<T, n, kazu::base::vecD<T, n> >::vector_type 
     
     
    template<typename T>
    typename kazu::math::vecmath<T, 2>::vector_type
    kazu::math::vecmath<T, 2>::cross(
    							   typename kazu::math::vecmath<T, 2>::vector_type& rhv,
    							   typename kazu::math::vecmath<T, 2>::vector_type& lhv)
    {
     
    	//impl
    	return typename kazu::math::vecmath<T, 2>::vector_type(rhv.x* lhv.y, rhv.y * lhv.x);
    }
     
     
    template<typename T>
    typename kazu::math::vecmath<T, 2>::scalar_type
    kazu::math::vecmath<T, 2>::dot(
    							   typename kazu::math::vecmath<T, 2>::vector_type& rhv,
    							   typename kazu::math::vecmath<T, 2>::vector_type& lhv)
    {
     
    	//impl
    	return typename kazu::math::vecmath<T, 2>::value_type(0);
    }
     
     
     
    int main (int argc, char * const argv[]) 
    {
    	//using kazu::blast<float>;
     
    	kazu::blast<float>::vec2 a2;
    	kazu::blast<float>::vec2 b2;
    	kazu::blast<float>::vec2 c2(kazu::blast<float>::vec2::cross(a2, b2));
    	float dot2 = kazu::blast<float>::vec2::dot(a2, c2);
     
    	kazu::blast<float>::vec3 a3;
    	kazu::blast<float>::vec3 b3;
    	kazu::blast<float>::vec3 c3(kazu::blast<float>::vec3::cross(a3, b3));
    	float dot3 = kazu::blast<float>::vec3::dot(a3, c3);
     
     
     
        // insert code here...
        std::cout << "Hello, World!\n" << dot2 << dot3;
        return 0;
    }
    Donc, il ne reconnait pas la définition de la structure. Comment remedier à cette erreur?

  11. #11
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Points : 13 017
    Points
    13 017
    Par défaut
    Le problème c'est que tu veux définir une méthode d'une spécialisation partielle que tu n'as pas définis :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    template<typename T>
    typename kazu::math::vecmath<T, 2>::vector_type
    kazu::math::vecmath<T, 2>::cross(
    							   typename kazu::math::vecmath<T, 2>::vector_type& rhv,
    							   typename kazu::math::vecmath<T, 2>::vector_type& lhv)
    {
     
    	//impl
    	return typename kazu::math::vecmath<T, 2>::vector_type(rhv.x* lhv.y, rhv.y * lhv.x);
    }
    vecmath<T, 2> est une spécialisation partielle non définie.

  12. #12
    Expert confirmé
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Décembre 2003
    Messages
    3 549
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Décembre 2003
    Messages : 3 549
    Points : 4 625
    Points
    4 625
    Par défaut
    De toutes manières, spécialiser partiellement une classe nécessite de redéfinir toute la classe, tu ne peux pas juste changer des fonctions membres.
    Boost ftw

  13. #13
    Membre averti
    Homme Profil pro
    Game Graphics Programmer
    Inscrit en
    Août 2006
    Messages
    408
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Allemagne

    Informations professionnelles :
    Activité : Game Graphics Programmer
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Août 2006
    Messages : 408
    Points : 392
    Points
    392
    Par défaut
    Ah, ok. Je vois l'erreur. J'étais parti du principe que la classe était définie de facon générique et qu'elle n'avait donc pas besoin d'être redefinie de facon partielle.

    Je vais corriger ca. Mais du coup, si je dois redefinir toutes les classes pour les spécialisation partielles, ca enlève un peu l'intérêt de la chose en fait, intérêt qui résidait surtout dans le fait d'avoir moins de code à écrire.

    En tout cas, merci de m'avoir illuminé sur ce sujet.

    Du coup, je cherche de la documentation sur les templates et le C++ de haut-niveau comme celui-ci (en dehors de la FAQ, genre des livres à recommander).

  14. #14
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 612
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 612
    Points : 30 612
    Points
    30 612
    Par défaut
    Salut,

    Par contre, ce que tu peux faire, c'est, à l'intérieur d'une classe qui ne sera pas partiellement spécialisée, créer une fonction objet, template, qui, elle, le sera spécialisée (partiellement ou totalement, selon les besoins )

    Cela pourrait prendre une forme proche de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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
    template <class T>
    class MyClass
    {
        private:
            template typename T value_type; // par facilité, uniquement ;)
            template <class U>
            class ObjectFunction
            {
                static void operator()(U const& item)
                {
                    /* ce qui doit etre fait */
                }
            };
            template <>
            class ObjectFunction<SpecialisedType>
             {
                 staticvoid operator(SpecialisedType const & item)
                  {
                      /*comportement spécialisé */
                  }
             };
             public:
                 void doSomething(T const & arg)
                 {
                      ObjectFunction<MyClass::value_type>(arg);
                 }
    };
    Cela se base sur un principe proche des traits de politique (policy traits )
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  15. #15
    Membre averti
    Homme Profil pro
    Game Graphics Programmer
    Inscrit en
    Août 2006
    Messages
    408
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Allemagne

    Informations professionnelles :
    Activité : Game Graphics Programmer
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Août 2006
    Messages : 408
    Points : 392
    Points
    392
    Par défaut
    Merci pour cette excellente idée. Ca pourrait très fonctionner pour mon exemple.

    Seule remarque, si je voulais maintenant spécialiser pour une type donnée (j'imagine très bien la spécialisation totale pour un vecteurde longueur 3 et de type float qui utilise les extension SSE (ou Altivec) pour être rapide), comment est-ce que je pourrais écrire ca?

    Dans mon exemple au-dessus, je devrais refaire une spécialisation totale de la classe (ou du moins de la fonction) dans le cas précis.

    En fait, quelle serait la facon qui me donne le plus de libertés quant à l'implémentation des fonctions en rapport avec le moins de code "doublon" possible?

  16. #16
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 612
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 612
    Points : 30 612
    Points
    30 612
    Par défaut
    Tu peux tout à fait prévoir plus d'un paramètre template dans ta fonction objet...

    Cela pourrait prendre la forme de
    /* une fonction générique, sur laquelle nous ne savons rien
    * (mais qui n'utilise pas, par défaut, SSE)
    template <class Container, typename Type, bool UseSSE = false>
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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
    class ObjectFunction
    {
        public:
            typedef typename Container<T> container; // un typedef du conteneur
            typedef container::iterator iterator; // un typedef pour les itérateurs
            typedef container::const_iterator const_iterator; //un typedef d'itérateur constant;
             typedef container::value_type value_type; //le type de donnée
        static void operator()(container const& c)
        {
             /*...*/
        };
    };
    /* la spécialisation total de la fonction objet pour un vecteur 
     * de float et qui utilise SSE
     */
    template <>
    class ObjectFunction<std::vector, float, true>
    {
        public:
            typedef typename std::vector<float> container; // un typedef du conteneur
            typedef container::iterator iterator; // un typedef pour les itérateurs
            typedef container::const_iterator const_iterator; //un typedef d'itérateur constant;
            typedef container::value_type value_type; //le type de donnée
        static void operator()(container const& c)
        {
             /*...*/
        };
    };
    Tu peux aussi décidé de recourir à l'héritage, et d'avoir donc une hérarchie proche de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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
    /* une classe qui s'occupe simplement de la généralisation du conteneur */
    template <class Container, typename type>
    class MyTContainer
    {
        public:
        typedef typename Container<type> container;
        typedef container::iterator iterator;
        typedef container::const_iterator const_iterator;
        typedef container::value_type value_type;
    };
    /* la classe utilisant un vecteur de float commecontainer 
     * et utilisant ou non SSE */
    template < template<> class Container>
    class MyFloatingPointVector: public MyContainer<std::vector, float>
    {
    };
    /* un trait de politique spécifiant s'il faut utiliser SSE
     */
    template <bool >
    class UsingSSETrait
    {
        public:
            enum {useSSE = false};
    };
    template <>
    class UsingSSETrait<true>
    {
        public:
            enum {useSSE = true};
    };
    Avec ta fonction objet qui prendra une forme proche de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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
    /* une déclaration uniquement pour tout ce qui tenterait de l'utiser
     * sans que ce soit un MyTContainer ou qui n'utiliserait pas UsingSSETrait
     */
    template <class Container, class sseTrait>
    class ObjectFunction;
    /* une spécialisation pour le cas général (on ne sait ni quel
     * conteneur est utilisé, ni avec quel type, ni s'il faut utiliser
     * SSE
     */
    template<>
    class ObjectFunction<MyTContainer, UsingSSETrait>
    {
        static void operator()(/*...*/ ) 
        {
        }
    };
    /* une spécialisation pour ce qui utilise un MyFloatingPointVector
     * mais pas SSE (si tu veux qu'il agisse différemment du "cas tout à fait
     * indéterminé" )
     */
     
    template<>
    class ObjectFunction<MyFloatingPointVector, UsingSSETrait<false> >
    {
        static void operator()(/*...*/ )
        {
        }
    };
    /* et enfin, une spécialisation pour le vector<float> utilisant SSE
     */
    template<>
    class ObjectFunction<MyFloatingPointVector, UsingSSETrait<true> >
    {
        public:
        static void operator()(/*...*/ )
        {
        }
    };
    NOTA : Tu pourrais aussi éviter la dernière spécialisation en introduisant dans la deuxième un opérateur ternaire ? sur UsingSSETrait::useSSE qui pourrait prendre une forme proche de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    template<bool b = true /* ou false, selon ta préférence ;) */ >
    class ObjectFunction<MyFloatingPointVector, UsingSSETrait<b> >
    {
        private:
            static inline void processWithSSE(/*...*/) 
            {
                /* ce qui doit etre fait avec SSE */
            }
            static inline void processWithoutSSE(/*...*/)
            {
                /* ce qui doit être fait sans SSE */
            }
        public:
            static void operator()(/*...*/ )
            {
                 UsingSSETrait<b>::useSSE ?
                     processWithSSE(/*...*/) :
                     processWithoutSSE(/*...*/);
            }
    };
    L'opérateur ternaire ? a en effet cette caractéristique géniale de pouvoir être interprété à la compilation, ce qui permet de faire appel uniquement à processWithSSE ou à processWithoutSSE en fonction de b

    Les codes n'ont pas été testés et contiennent peut être une erreur ou l'autre, mais une recherche sur le forum ou sur le net en général devrait te permettre de trouver la solution aux erreurs commises
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

Discussions similaires

  1. Réponses: 2
    Dernier message: 02/05/2011, 21h58
  2. Conversion de type
    Par poirier dans le forum ASP
    Réponses: 2
    Dernier message: 06/07/2004, 10h30
  3. [MYSQL] conversion de type sur import de script
    Par sebos63 dans le forum SQL Procédural
    Réponses: 2
    Dernier message: 27/08/2003, 10h00
  4. Réponses: 2
    Dernier message: 05/06/2002, 12h29

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo