Je travaille sur un projet de traitement d'image. J'ai une classe
Image template sur le type de pixel. La classe propose un certain
nombre de fonctionnalités communes à tous les types (copier, convertir
vers un autre format de pixel, tracer des traits, des cercles...). Il
y a toutefois certaines opérations qui n'ont de sens que pour certains
types de pixels : par exemple calculer le gradient ne peut se faire
(ou du moins avec ma bibliotheque) que sur des images en niveau de
gris.
J'ai imaginé avoir un truc comme ca :
template<class PixType>
class Image
{
public:
void Gradient()
{
const Image<PixGray*> compileTimeError = this;
}
};
mais c'est pas vraiment satisfaisant d'avoir la fonction dans toutes
les classes avec un truc qui compile pas si on tente de l'appeler.
J'ai aussi pensé faire comme ca :
template<class PixType>
class ImageBase
{
public:
// Fonctions communes à tous les types
};
template<class PixType>
class Image : public ImageBase<PixType>
{ };
template<>
class Image<PixGray> : public ImageBase<PixGray>
{
public:
// Fonctions juste pour PixGray
};
mais maintenant je voudrais ajouter une fonction (la même, avec la
même implémentation) à PixRGB, PixYCrCb, et PixHSV (pour info c'est la
séparation en 3 images PixGray pour les channels), et les deux
méthodes précédentes atteignent leur limites.
Est ce qu'il y a une façon de faire ce que je veux : une sorte de truc
comme ca :
template<class PixType>
class Image
{
public:
<if PixType == PixGray> // Comment ca s'écrit ?
void Gradient()
{
//...
}
</if>
<if PixType in { PixRGB, PixYCrCb, PixHSV } >
// ou mieux: <if PixType::cChannels == 3>
void SplitChannels(/* ... */)
{
// ...
}
</if>
};
Cette action est irreversible, confirmez la suppression du commentaire ?
Signaler le commentaire
Veuillez sélectionner un problème
Nudité
Violence
Harcèlement
Fraude
Vente illégale
Discours haineux
Terrorisme
Autre
Fabien LE LEZ
On Mon, 09 Apr 2007 19:49:48 -0700, Vincent Lascaux :
template<class PixType> class Image { public: void Gradient()
Pourquoi la fonction Gradient() devrait-elle être membre ?
J'imagine que cette fonction lit des pixels, puis modifie des pixels. Et je suppose que la classe a déjà des fonctions publiques qui permettent de lire et modifier des pixels.
En d'autres termes, Gradient() peut très bien être une fonction libre, qui fera son boulot en utilisant l'interface publique de Image<>.
template<class PixType> class Image { ... };
void Gradient (Image<PixGray>& image);
Supposons maintenant que tu souhaites rendre la fonction Gradient() template, pour pouvoir accepter certains types et pas d'autres. On peut faire ça, indirectement, très facilement :
Comme la fonction template DoGradient<> est visible uniquement de ton code (i.e. dans le .cpp), tu es assuré qu'on ne l'appellera qu'avec les types qui vont bien.
On Mon, 09 Apr 2007 19:49:48 -0700, Vincent Lascaux
<vincent.lascaux@invalid>:
template<class PixType>
class Image
{
public:
void Gradient()
Pourquoi la fonction Gradient() devrait-elle être membre ?
J'imagine que cette fonction lit des pixels, puis modifie des pixels.
Et je suppose que la classe a déjà des fonctions publiques qui
permettent de lire et modifier des pixels.
En d'autres termes, Gradient() peut très bien être une fonction libre,
qui fera son boulot en utilisant l'interface publique de Image<>.
template<class PixType>
class Image
{ ... };
void Gradient (Image<PixGray>& image);
Supposons maintenant que tu souhaites rendre la fonction Gradient()
template, pour pouvoir accepter certains types et pas d'autres.
On peut faire ça, indirectement, très facilement :
Comme la fonction template DoGradient<> est visible uniquement de ton
code (i.e. dans le .cpp), tu es assuré qu'on ne l'appellera qu'avec
les types qui vont bien.
On Mon, 09 Apr 2007 19:49:48 -0700, Vincent Lascaux :
template<class PixType> class Image { public: void Gradient()
Pourquoi la fonction Gradient() devrait-elle être membre ?
J'imagine que cette fonction lit des pixels, puis modifie des pixels. Et je suppose que la classe a déjà des fonctions publiques qui permettent de lire et modifier des pixels.
En d'autres termes, Gradient() peut très bien être une fonction libre, qui fera son boulot en utilisant l'interface publique de Image<>.
template<class PixType> class Image { ... };
void Gradient (Image<PixGray>& image);
Supposons maintenant que tu souhaites rendre la fonction Gradient() template, pour pouvoir accepter certains types et pas d'autres. On peut faire ça, indirectement, très facilement :
Comme la fonction template DoGradient<> est visible uniquement de ton code (i.e. dans le .cpp), tu es assuré qu'on ne l'appellera qu'avec les types qui vont bien.
Vincent Lascaux
Pourquoi la fonction Gradient() devrait-elle être membre ?
Hum... Effectivement, ca résoud le problème...
Tracer la frontiere entre méthode et fonctions "globales" est assez flou (ou du moins me semble assez flou).
Gradient est une opération qui s'effectue sur une image, c'est pour ca que je voulais l'avoir comme une méthode de la classe.
Est ce que Fill(const PixType& color) qui remplit l'image avec une valeur constante devrait faire parti de la classe Image ou pas ?
Bref, tu serais pour que Image soit très très minimaliste (constructeur, destructeur, resize et get/set pixel), et que tout le reste soit des méthodes globales ? C'est une façon de voir les choses, je suis pas sur que ce soit la plus OO qu'il soit.
-- Vincent
Pourquoi la fonction Gradient() devrait-elle être membre ?
Hum... Effectivement, ca résoud le problème...
Tracer la frontiere entre méthode et fonctions "globales" est assez
flou (ou du moins me semble assez flou).
Gradient est une opération qui s'effectue sur une image, c'est pour
ca que je voulais l'avoir comme une méthode de la classe.
Est ce que Fill(const PixType& color) qui remplit l'image avec une
valeur constante devrait faire parti de la classe Image ou pas ?
Bref, tu serais pour que Image soit très très minimaliste
(constructeur, destructeur, resize et get/set pixel), et que tout le
reste soit des méthodes globales ? C'est une façon de voir les choses,
je suis pas sur que ce soit la plus OO qu'il soit.
Pourquoi la fonction Gradient() devrait-elle être membre ?
Hum... Effectivement, ca résoud le problème...
Tracer la frontiere entre méthode et fonctions "globales" est assez flou (ou du moins me semble assez flou).
Gradient est une opération qui s'effectue sur une image, c'est pour ca que je voulais l'avoir comme une méthode de la classe.
Est ce que Fill(const PixType& color) qui remplit l'image avec une valeur constante devrait faire parti de la classe Image ou pas ?
Bref, tu serais pour que Image soit très très minimaliste (constructeur, destructeur, resize et get/set pixel), et que tout le reste soit des méthodes globales ? C'est une façon de voir les choses, je suis pas sur que ce soit la plus OO qu'il soit.
-- Vincent
Fabien LE LEZ
On Mon, 09 Apr 2007 22:24:23 -0700, Vincent Lascaux :
Note en passant : je déconseille fortement l'usage du mot "méthode" pour désigner une fonction, au moins dans le cadre du C++. En effet, il ne semble pas y avoir de consensus sur la définition de ce mot. Les deux définitions les plus courantes sont "fonction membre" et "fonction membre virtuelle", mais tu sembles en avoir une troisième, puisque tu emploies ce mot pour désigner une fonction libre (i.e. non membre d'une classe).
Tracer la frontiere entre méthode et fonctions "globales" est assez flou (ou du moins me semble assez flou).
Une fonction membre a accès aux membres privés. Il me semble qu'une fonction qui n'a pas besoin d'y avoir accès ne devrait pas être membre.
Par ailleurs, une fonction libre peut être séparée de la classe : si tu en as beaucoup, tu peux les mettre dans un .h séparé, et n'inclure ce .h que dans les .cpp qui en ont besoin. Par exemple, si un .cpp a besoin de la classe Image mais pas de la fonction Gradient, il peut inclure le .h qui contient Image, mais pas celui qui contient Gradient -- ça réduit d'autant les ressources nécessaires pour compiler, et ça rend le code plus simple à comprendre.
Cf aussi l'article de Sutter à ce sujet : <http://www.gotw.ca/gotw/084.htm>.
Bref, tu serais pour que Image soit très très minimaliste (constructeur, destructeur, resize et get/set pixel), et que tout le reste soit des méthodes globales ? C'est une façon de voir les choses, je suis pas sur que ce soit la plus OO qu'il soit.
Il me semble que si, au contraire : les variables membres sont privées, et le moins possible de fonctions y ont accès. Si une fonction n'a pas besoin d'avoir accès aux membres privés, il ne faut pas le lui donner.
Ajoutons également que la POO n'est jamais qu'un paradigme parmi d'autres. En d'autres termes, un outil, qu'il faut utiliser quand on en a besoin.
On Mon, 09 Apr 2007 22:24:23 -0700, Vincent Lascaux :
Note en passant : je déconseille fortement l'usage du mot "méthode"
pour désigner une fonction, au moins dans le cadre du C++. En effet,
il ne semble pas y avoir de consensus sur la définition de ce mot.
Les deux définitions les plus courantes sont "fonction membre" et
"fonction membre virtuelle", mais tu sembles en avoir une troisième,
puisque tu emploies ce mot pour désigner une fonction libre (i.e. non
membre d'une classe).
Tracer la frontiere entre méthode et fonctions "globales" est assez
flou (ou du moins me semble assez flou).
Une fonction membre a accès aux membres privés. Il me semble qu'une
fonction qui n'a pas besoin d'y avoir accès ne devrait pas être
membre.
Par ailleurs, une fonction libre peut être séparée de la classe : si
tu en as beaucoup, tu peux les mettre dans un .h séparé, et n'inclure
ce .h que dans les .cpp qui en ont besoin.
Par exemple, si un .cpp a besoin de la classe Image mais pas de la
fonction Gradient, il peut inclure le .h qui contient Image, mais pas
celui qui contient Gradient -- ça réduit d'autant les ressources
nécessaires pour compiler, et ça rend le code plus simple à
comprendre.
Cf aussi l'article de Sutter à ce sujet :
<http://www.gotw.ca/gotw/084.htm>.
Bref, tu serais pour que Image soit très très minimaliste
(constructeur, destructeur, resize et get/set pixel), et que tout le
reste soit des méthodes globales ? C'est une façon de voir les choses,
je suis pas sur que ce soit la plus OO qu'il soit.
Il me semble que si, au contraire : les variables membres sont
privées, et le moins possible de fonctions y ont accès.
Si une fonction n'a pas besoin d'avoir accès aux membres privés, il ne
faut pas le lui donner.
Ajoutons également que la POO n'est jamais qu'un paradigme parmi
d'autres. En d'autres termes, un outil, qu'il faut utiliser quand on
en a besoin.
On Mon, 09 Apr 2007 22:24:23 -0700, Vincent Lascaux :
Note en passant : je déconseille fortement l'usage du mot "méthode" pour désigner une fonction, au moins dans le cadre du C++. En effet, il ne semble pas y avoir de consensus sur la définition de ce mot. Les deux définitions les plus courantes sont "fonction membre" et "fonction membre virtuelle", mais tu sembles en avoir une troisième, puisque tu emploies ce mot pour désigner une fonction libre (i.e. non membre d'une classe).
Tracer la frontiere entre méthode et fonctions "globales" est assez flou (ou du moins me semble assez flou).
Une fonction membre a accès aux membres privés. Il me semble qu'une fonction qui n'a pas besoin d'y avoir accès ne devrait pas être membre.
Par ailleurs, une fonction libre peut être séparée de la classe : si tu en as beaucoup, tu peux les mettre dans un .h séparé, et n'inclure ce .h que dans les .cpp qui en ont besoin. Par exemple, si un .cpp a besoin de la classe Image mais pas de la fonction Gradient, il peut inclure le .h qui contient Image, mais pas celui qui contient Gradient -- ça réduit d'autant les ressources nécessaires pour compiler, et ça rend le code plus simple à comprendre.
Cf aussi l'article de Sutter à ce sujet : <http://www.gotw.ca/gotw/084.htm>.
Bref, tu serais pour que Image soit très très minimaliste (constructeur, destructeur, resize et get/set pixel), et que tout le reste soit des méthodes globales ? C'est une façon de voir les choses, je suis pas sur que ce soit la plus OO qu'il soit.
Il me semble que si, au contraire : les variables membres sont privées, et le moins possible de fonctions y ont accès. Si une fonction n'a pas besoin d'avoir accès aux membres privés, il ne faut pas le lui donner.
Ajoutons également que la POO n'est jamais qu'un paradigme parmi d'autres. En d'autres termes, un outil, qu'il faut utiliser quand on en a besoin.
Franck Branjonneau
Vincent Lascaux écrivait:
Je travaille sur un projet de traitement d'image. J'ai une classe Image template sur le type de pixel. La classe propose un certain nombre de fonctionnalités communes à tous les types (copier, convertir vers un autre format de pixel, tracer des traits, des cercles...). Il y a toutefois certaines opérations qui n'ont de sens que pour certains types de pixels : par exemple calculer le gradient ne peut se faire (ou du moins avec ma bibliotheque) que sur des images en niveau de gris.
J'ai aussi pensé faire comme ca :
template<class PixType> class ImageBase { public: // Fonctions communes à tous les types };
template<class PixType> class Image : public ImageBase { };
template<> class Image : public ImageBase { public: // Fonctions juste pour PixGray };
Je lis Image< PixGray > ici.
mais maintenant je voudrais ajouter une fonction (la même, avec la même implémentation) à PixRGB, PixYCrCb, et PixHSV (pour info c'est la séparation en 3 images PixGray pour les channels), et les deux méthodes précédentes atteignent leur limites.
La proposition de Fabien me semble pertinente.
Est ce qu'il y a une façon de faire ce que je veux : une sorte de truc comme ca : template<class PixType> class Image { public: <if PixType == PixGray> // Comment ca s'écrit ? void Gradient() { //... } </if> <if PixType in { PixRGB, PixYCrCb, PixHSV } > // ou mieux: <if PixType::cChannels == 3> void SplitChannels(/* ... */) { // ... } </if> };
Utiliser un type de base ayant plus de paramètres et spécialiser selon la valeur de ces parmètres :
template< typename _Pixel > struct BasicImage: public BasicBaseImage< _Pixel >, public Gradient< Pixel::hasGradient >, public SplitChannel< Pixel::colorChannels > {
// typedef_s + using_s from BasicBaseImage< _Pixel > using Gradient< Pixel::hasGradient >::gradient; using SplitChannel< Pixel::colorChannels >::splitChannel; };
template< bool _hasGradient > struct Gradient {
// Not implemented void gradient() const; };
template<> struct Gradient< true > {
void gradient() const; };
template< int _colorChannels > struct SplitChannel {
// Not implemented void splitChannel() const; };
template<> struct SplitChannel< 3 > {
void splitChannel() const; };
-- Franck Branjonneau
Vincent Lascaux <vincent.lascaux@invalid> écrivait:
Je travaille sur un projet de traitement d'image. J'ai une classe
Image template sur le type de pixel. La classe propose un certain
nombre de fonctionnalités communes à tous les types (copier, convertir
vers un autre format de pixel, tracer des traits, des cercles...). Il
y a toutefois certaines opérations qui n'ont de sens que pour certains
types de pixels : par exemple calculer le gradient ne peut se faire
(ou du moins avec ma bibliotheque) que sur des images en niveau de
gris.
J'ai aussi pensé faire comme ca :
template<class PixType>
class ImageBase
{
public:
// Fonctions communes à tous les types
};
template<class PixType>
class Image : public ImageBase
{ };
template<>
class Image : public ImageBase
{
public:
// Fonctions juste pour PixGray
};
Je lis Image< PixGray > ici.
mais maintenant je voudrais ajouter une fonction (la même, avec la
même implémentation) à PixRGB, PixYCrCb, et PixHSV (pour info c'est la
séparation en 3 images PixGray pour les channels), et les deux
méthodes précédentes atteignent leur limites.
La proposition de Fabien me semble pertinente.
Est ce qu'il y a une façon de faire ce que je veux : une sorte de truc
comme ca :
template<class PixType>
class Image
{
public:
<if PixType == PixGray> // Comment ca s'écrit ?
void Gradient()
{
//...
}
</if>
<if PixType in { PixRGB, PixYCrCb, PixHSV } >
// ou mieux: <if PixType::cChannels == 3>
void SplitChannels(/* ... */)
{
// ...
}
</if>
};
Utiliser un type de base ayant plus de paramètres et spécialiser selon la
valeur de ces parmètres :
Je travaille sur un projet de traitement d'image. J'ai une classe Image template sur le type de pixel. La classe propose un certain nombre de fonctionnalités communes à tous les types (copier, convertir vers un autre format de pixel, tracer des traits, des cercles...). Il y a toutefois certaines opérations qui n'ont de sens que pour certains types de pixels : par exemple calculer le gradient ne peut se faire (ou du moins avec ma bibliotheque) que sur des images en niveau de gris.
J'ai aussi pensé faire comme ca :
template<class PixType> class ImageBase { public: // Fonctions communes à tous les types };
template<class PixType> class Image : public ImageBase { };
template<> class Image : public ImageBase { public: // Fonctions juste pour PixGray };
Je lis Image< PixGray > ici.
mais maintenant je voudrais ajouter une fonction (la même, avec la même implémentation) à PixRGB, PixYCrCb, et PixHSV (pour info c'est la séparation en 3 images PixGray pour les channels), et les deux méthodes précédentes atteignent leur limites.
La proposition de Fabien me semble pertinente.
Est ce qu'il y a une façon de faire ce que je veux : une sorte de truc comme ca : template<class PixType> class Image { public: <if PixType == PixGray> // Comment ca s'écrit ? void Gradient() { //... } </if> <if PixType in { PixRGB, PixYCrCb, PixHSV } > // ou mieux: <if PixType::cChannels == 3> void SplitChannels(/* ... */) { // ... } </if> };
Utiliser un type de base ayant plus de paramètres et spécialiser selon la valeur de ces parmètres :
template< typename _Pixel > struct BasicImage: public BasicBaseImage< _Pixel >, public Gradient< Pixel::hasGradient >, public SplitChannel< Pixel::colorChannels > {
// typedef_s + using_s from BasicBaseImage< _Pixel > using Gradient< Pixel::hasGradient >::gradient; using SplitChannel< Pixel::colorChannels >::splitChannel; };
template< bool _hasGradient > struct Gradient {
// Not implemented void gradient() const; };
template<> struct Gradient< true > {
void gradient() const; };
template< int _colorChannels > struct SplitChannel {
// Not implemented void splitChannel() const; };
template<> struct SplitChannel< 3 > {
void splitChannel() const; };
-- Franck Branjonneau
Mathias Gaunard
Est ce qu'il y a une façon de faire ce que je veux : une sorte de truc comme ca : template<class PixType> class Image { public: <if PixType == PixGray> // Comment ca s'écrit ? void Gradient() { //... } </if>
Ce genre de choses peut se faire par exemple avec SFINAE.
Est ce qu'il y a une façon de faire ce que je veux : une sorte de truc
comme ca :
template<class PixType>
class Image
{
public:
<if PixType == PixGray> // Comment ca s'écrit ?
void Gradient()
{
//...
}
</if>
Ce genre de choses peut se faire par exemple avec SFINAE.
Est ce qu'il y a une façon de faire ce que je veux : une sorte de truc comme ca : template<class PixType> class Image { public: <if PixType == PixGray> // Comment ca s'écrit ? void Gradient() { //... } </if>
Ce genre de choses peut se faire par exemple avec SFINAE.
template<class PixType> class Image { public: void Gradient() { const Image<PixGray*> compileTimeError = this; } }; mais c'est pas vraiment satisfaisant d'avoir la fonction dans toutes les classes avec un truc qui compile pas si on tente de l'appeler.
Une fonction template n'est instanciée que si elle est utilisée. Donc ta fonction ne sera que dans des classes où elle est utilisable. Et avoir un truc qui ne compile pas me semble le meilleur niveau d'erreur qu'on puisse obtenir.
Juste 1 ou 2 points : Que se passe-il si tu ajoutes une fonction permettant de convertir un Image<ColorPix*> en Image<PixGray*> ? Plutôt que de copier le tableau, pourquoi ne pas prendre une référence dessus ? Voire même avoir un contrôle statique ne faisant rien au runtime (boost::static_assert, avec boost::type_traits::is_same, devrait pouvoir t'aider).
Le truc avec enable_if me semble en l'occurence beaucoup trop malin, et en plus apparait dans la déclaration, ce qui à mon avis l'embrouille.
-- Loïc
template<class PixType>
class Image
{
public:
void Gradient()
{
const Image<PixGray*> compileTimeError = this;
}
};
mais c'est pas vraiment satisfaisant d'avoir la fonction dans toutes
les classes avec un truc qui compile pas si on tente de l'appeler.
Une fonction template n'est instanciée que si elle est utilisée. Donc ta
fonction ne sera que dans des classes où elle est utilisable. Et avoir
un truc qui ne compile pas me semble le meilleur niveau d'erreur qu'on
puisse obtenir.
Juste 1 ou 2 points : Que se passe-il si tu ajoutes une fonction
permettant de convertir un Image<ColorPix*> en Image<PixGray*> ?
Plutôt que de copier le tableau, pourquoi ne pas prendre une référence
dessus ? Voire même avoir un contrôle statique ne faisant rien au
runtime (boost::static_assert, avec boost::type_traits::is_same, devrait
pouvoir t'aider).
Le truc avec enable_if me semble en l'occurence beaucoup trop malin, et
en plus apparait dans la déclaration, ce qui à mon avis l'embrouille.
template<class PixType> class Image { public: void Gradient() { const Image<PixGray*> compileTimeError = this; } }; mais c'est pas vraiment satisfaisant d'avoir la fonction dans toutes les classes avec un truc qui compile pas si on tente de l'appeler.
Une fonction template n'est instanciée que si elle est utilisée. Donc ta fonction ne sera que dans des classes où elle est utilisable. Et avoir un truc qui ne compile pas me semble le meilleur niveau d'erreur qu'on puisse obtenir.
Juste 1 ou 2 points : Que se passe-il si tu ajoutes une fonction permettant de convertir un Image<ColorPix*> en Image<PixGray*> ? Plutôt que de copier le tableau, pourquoi ne pas prendre une référence dessus ? Voire même avoir un contrôle statique ne faisant rien au runtime (boost::static_assert, avec boost::type_traits::is_same, devrait pouvoir t'aider).
Le truc avec enable_if me semble en l'occurence beaucoup trop malin, et en plus apparait dans la déclaration, ce qui à mon avis l'embrouille.
-- Loïc
Loïc Joly
template<class PixType> class Image { public: void Gradient() { const Image<PixGray*> compileTimeError = this; } }; mais c'est pas vraiment satisfaisant d'avoir la fonction dans toutes les classes avec un truc qui compile pas si on tente de l'appeler.
Une fonction template n'est instanciée que si elle est utilisée. Donc ta fonction ne sera que dans des classes où elle est utilisable. Et avoir un truc qui ne compile pas me semble le meilleur niveau d'erreur qu'on puisse obtenir.
Juste une précision : C'est déjà la méthode largement utilisée par la STL, comme dans std::list::sort, ou dans le constructeur de vector qui prend uniquement une taille. Ca pourra certainement s'exprimer plus clairement quand il y aura des concepts en C++ (bientôt j'espère), mais en attendant, je ne suis pas trop pour les astuces à base de template qui alourdissent le code plus qu'elles ne le clarifient.
-- Loïc
template<class PixType>
class Image
{
public:
void Gradient()
{
const Image<PixGray*> compileTimeError = this;
}
};
mais c'est pas vraiment satisfaisant d'avoir la fonction dans toutes
les classes avec un truc qui compile pas si on tente de l'appeler.
Une fonction template n'est instanciée que si elle est utilisée. Donc ta
fonction ne sera que dans des classes où elle est utilisable. Et avoir
un truc qui ne compile pas me semble le meilleur niveau d'erreur qu'on
puisse obtenir.
Juste une précision : C'est déjà la méthode largement utilisée par la
STL, comme dans std::list::sort, ou dans le constructeur de vector qui
prend uniquement une taille. Ca pourra certainement s'exprimer plus
clairement quand il y aura des concepts en C++ (bientôt j'espère), mais
en attendant, je ne suis pas trop pour les astuces à base de template
qui alourdissent le code plus qu'elles ne le clarifient.
template<class PixType> class Image { public: void Gradient() { const Image<PixGray*> compileTimeError = this; } }; mais c'est pas vraiment satisfaisant d'avoir la fonction dans toutes les classes avec un truc qui compile pas si on tente de l'appeler.
Une fonction template n'est instanciée que si elle est utilisée. Donc ta fonction ne sera que dans des classes où elle est utilisable. Et avoir un truc qui ne compile pas me semble le meilleur niveau d'erreur qu'on puisse obtenir.
Juste une précision : C'est déjà la méthode largement utilisée par la STL, comme dans std::list::sort, ou dans le constructeur de vector qui prend uniquement une taille. Ca pourra certainement s'exprimer plus clairement quand il y aura des concepts en C++ (bientôt j'espère), mais en attendant, je ne suis pas trop pour les astuces à base de template qui alourdissent le code plus qu'elles ne le clarifient.
-- Loïc
Mathias Gaunard
template<class PixType> class Image { public: void Gradient() { const Image<PixGray*> compileTimeError = this; } }; mais c'est pas vraiment satisfaisant d'avoir la fonction dans toutes les classes avec un truc qui compile pas si on tente de l'appeler.
Une fonction template n'est instanciée que si elle est utilisée.
Gradient n'est pas une fonction template, mais une fonction membre d'une classe template.
template<class PixType>
class Image
{
public:
void Gradient()
{
const Image<PixGray*> compileTimeError = this;
}
};
mais c'est pas vraiment satisfaisant d'avoir la fonction dans toutes
les classes avec un truc qui compile pas si on tente de l'appeler.
Une fonction template n'est instanciée que si elle est utilisée.
Gradient n'est pas une fonction template, mais une fonction membre d'une
classe template.
template<class PixType> class Image { public: void Gradient() { const Image<PixGray*> compileTimeError = this; } }; mais c'est pas vraiment satisfaisant d'avoir la fonction dans toutes les classes avec un truc qui compile pas si on tente de l'appeler.
Une fonction template n'est instanciée que si elle est utilisée.
Gradient n'est pas une fonction template, mais une fonction membre d'une classe template.
Loïc Joly
Gradient n'est pas une fonction template, mais une fonction membre d'une classe template.
Effectivement, problème de vocabulaire. Il n'en reste pas moins qu'il n'y aura pas instanciation sauf si nécessaire.
14.7.1.9 An implementation shall not implicitly instantiate a function template, a member template, a nonvirtual member function, a member class or a static data member of a class template that does not require instantiation.
-- Loïc
Gradient n'est pas une fonction template, mais une fonction membre
d'une classe template.
Effectivement, problème de vocabulaire. Il n'en reste pas moins qu'il
n'y aura pas instanciation sauf si nécessaire.
14.7.1.9
An implementation shall not implicitly instantiate a function
template, a member template, a nonvirtual member function, a member
class or a static data member of a class template that does not
require instantiation.
Gradient n'est pas une fonction template, mais une fonction membre d'une classe template.
Effectivement, problème de vocabulaire. Il n'en reste pas moins qu'il n'y aura pas instanciation sauf si nécessaire.
14.7.1.9 An implementation shall not implicitly instantiate a function template, a member template, a nonvirtual member function, a member class or a static data member of a class template that does not require instantiation.