Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

overloading ou spécialisation... telle est la question

11 réponses
Avatar
AG
Bonjour,

Voici ma fonction template:

template <class C>
string ReadFile::ValToString(C in)
{
ostringstream i;
i << in;
return i.str();
}

Mais pour les classes de types string, cette fonction ne fonctionne
pas pour plusieurs raisons:
l'op=E9rateur << s'arr=EAte au premier espace. En plus de cela je voudrais
rajouter des guillemets.

Donc j'ai fait une specialisation (?)

template<>
string ReadFile::ValToString(string in)
{
return "\"" + in + "\"";
}

qui a l'air de marcher.

Pour les classes de types C=3Dvector<T> ou m=EAme C=3Dvector<vector<T> > je
voudrais rajouter des parenth=E8ses. Donc j'ai fait:

template <>
string ReadFile::ValToString<vector<T> >(vector<T> in)
{
ostringstream i;
i << in;
return "(" + i.str() + ")";
}

cette derni=E8re fonction n'est bien s=FBr jamais appel=E9e. C'est la
fonction plus g=E9n=E9rale qui est appel=E9e =E0 la place. Est-ce qu'il exi=
ste
un moyen de contourner ce probl=E8me ? Je tourne sous visual.

Alexandre.

PS: j'oublierais pas de rajouter les const l=E0 ou il faut, promis :-)

10 réponses

1 2
Avatar
Jean-Marc Bourguet
AG writes:

Bonjour,

Voici ma fonction template:

template <class C>
string ReadFile::ValToString(C in)
{
ostringstream i;
i << in;
return i.str();
}

Mais pour les classes de types string, cette fonction ne fonctionne
pas pour plusieurs raisons:
l'opérateur << s'arrête au premier espace. En plus de cela je voudrais
rajouter des guillemets.

Donc j'ai fait une specialisation (?)

template<>
string ReadFile::ValToString(string in)
{
return """ + in + """;
}

qui a l'air de marcher.

Pour les classes de types C=vector<T> ou même C=vector<vector<T> > je
voudrais rajouter des parenthèses. Donc j'ai fait:

template <>
string ReadFile::ValToString<vector<T> >(vector<T> in)
{
ostringstream i;
i << in;
return "(" + i.str() + ")";
}

cette dernière fonction n'est bien sûr jamais appelée. C'est la
fonction plus générale qui est appelée à la place. Est-ce qu'il existe
un moyen de contourner ce problème ? Je tourne sous visual.



Tu peux essayer de donner un code minimal mais complet reproduisant le
probleme? (qu'est-ce que T ici par exemple).

A+

--
Jean-Marc
FAQ de fclc++: http://www.cmla.ens-cachan.fr/~dosreis/C++/FAQ
C++ FAQ Lite en VF: http://www.ifrance.com/jlecomte/c++/c++-faq-lite/index.html
Site de usenet-fr: http://www.usenet-fr.news.eu.org
Avatar
Mickaël Wolff
AG a écrit :
template <class C>
string ReadFile::ValToString(C in)
{
ostringstream i;
i << in;
return i.str();
}

Mais pour les classes de types string, cette fonction ne fonctionne
pas pour plusieurs raisons:
l'opérateur << s'arrête au premier espace. En plus de cela je voudrais
rajouter des guillemets.



Les flux fonctionnent en reconnaissant les formats de chaines. Si tu
ne veux pas que ton flux coupe les mots, il faut que tu désactive le
comportement. La fonction membre std::istream::setf avec
std::ios_base::skipws e l'entete <iomanip>.


--
Mickaël Wolff aka Lupus Michaelis
http://lupusmic.org
Avatar
FX
AG a écrit :
Pour les classes de types C=vector<T> ou même C=vector<vector<T> > je
voudrais rajouter des parenthèses. Donc j'ai fait:

template <>
string ReadFile::ValToString<vector<T> >(vector<T> in)
{
ostringstream i;
i << in;
return "(" + i.str() + ")";
}

cette dernière fonction n'est bien sûr jamais appelée. C'est la
fonction plus générale qui est appelée à la place. Est-ce qu'il existe
un moyen de contourner ce problème ? Je tourne sous visual.



Cette fonction ne compile pas chez moi, et pour cause: T n'est pas défini.

Je te propose donc plutôt:

template <class T>
string ReadFile::ValToString(vector<T> in)
{
ostringstream i;
i << in;
return "(" + i.str() + ")";
}

A condition que l'opérateur << soit défini avec un vector. Par exemple:

template <class T>
ostream& operator << (ostream &s, vector<T> &v)
{
vector<T>::iterator it;
for(it = v.begin(); it != v.end(); it++)
{
s << *it << ", ";
}
return s;
}


FX
Avatar
James Kanze
On Mar 11, 11:11 am, AG wrote:

Voici ma fonction template:

template <class C>
string ReadFile::ValToString(C in)
{
ostringstream i;
i << in;
return i.str();
}

Mais pour les classes de types string, cette fonction ne fonctionne
pas pour plusieurs raisons:
l'opérateur << s'arrête au premier espace. En plus de cela je voudrai s
rajouter des guillemets.

Donc j'ai fait une specialisation (?)

template<>
string ReadFile::ValToString(string in)
{
return """ + in + """;
}



C'est effectivement une specialisation. Un surcharge aurait
marché aussi, avec à peu près le même résultat.

qui a l'air de marcher.

Pour les classes de types C=vector<T> ou même C=vector<vector<T> > je
voudrais rajouter des parenthèses. Donc j'ai fait:

template <>
string ReadFile::ValToString<vector<T> >(vector<T> in)
{
ostringstream i;
i << in;
return "(" + i.str() + ")";
}



Et c'est quoi, T ?

Si j'ai bien compris, ce que tu veux, c'est une specialisation
partielle, et ça ne marche que pour les classes. Tu peux, en
revanche, surcharger un template de fonction avec un autre
template de fonction : dans le cas où la déduction de type
marche sur les deux, et les deux instantiations ne se
distinguent pas autrement, c'est celle en provenance du template
le plus spécialisé qui sera choisi. Donc, donné :

template<typename T>
std::string ReadFile::ValToString( T const& in );

template<typename T>
std::string ReadFile::ValToString( std::vector<T> const& in );

std::string ReadFile::ValToString( std::string const& in );

-- Pour la plupart des types, seulement la première est
viable ; elle sera donc choisie.

-- Pour std::string, le choix se fait entre la première et la
dernière. Dans de tels cas d'égalité, préférence est donnée
à la fonction qui n'est pas une instance d'un template.

-- Pour std::vector<int>, etc., le choix se fait entre la
première et la deuxième, avec préférence pour la deuxième,
parce que le template dont elle provient est plus
specialisé.

--
James Kanze
Avatar
Fabien LE LEZ
On Thu, 11 Mar 2010 22:18:12 +0100, FX :

template <class T>
ostream& operator << (ostream &s, vector<T> &v)
{
vector<T>::iterator it;



Attention, il manque les "const" un peu partout ici.
Avatar
AG
On Mar 11, 4:18 pm, Jean-Marc Bourguet wrote:
Tu peux essayer de donner un code minimal mais complet reproduisant le
probleme?  (qu'est-ce que T ici par exemple).



Bonjour Jean-Marc.

Oui voilà mon code minimal qui compile, tourne, mais ne fonctionne
pas. Je remarque que les autres on répondu, donc je vais voir ce
qu'ils disent. mais en attendant voilà mon code, sans les const un peu
partout comme il a déjà été fait remarqué. Je regarde les autres
réponses.

#include <iostream>
#include <sstream>
#include <vector>
#include <string>

using namespace std;

template<class C> ostream & operator<<(ostream &o, vector<C> v);

class A
{
public:
template<class C>
string ValToString(C & in);
template<class C>
string ValToString(vector<C> & in);
};

int main(int argc, char * argv[])
{
A a;
int i=3;
vector<int> v;
v.push_back(1);
v.push_back(3);
v.push_back(4);
cout << "3 -> " << a.ValToString<int>(i) << "n";
cout << "{1,3,4} -> " << a.ValToString<vector<int> >(v);
}

template<class C>
string A::ValToString(C &in)
{
ostringstream buff;
buff << in;
return buff.str();
}

template<class C>
string A::ValToString(std::vector<C> &in)
{
ostringstream buff;
buff << in;
return "(" + buff.str() + ")";
}

template<class C>
ostream & operator<<(ostream &o, vector<C> v)
{
vector<C>::iterator i;
for(i=v.begin();i!=v.end();++i)
{
o << *i << " ";
}
o << "n";
return o;
}
Avatar
AG
On Mar 11, 11:42 pm, James Kanze wrote:
 -- Pour std::vector<int>, etc., le choix se fait entre la
    première et la deuxième, avec préférence pour la deuxiè me,
    parce que le template dont elle provient est plus
    specialisé.


Bonjour James,

Dans l'exemple du code que j'ai posté plus haut, il semble que mon
compilo choisisse la première au lieu de la deuxième (les partenthèse s
ne sont pas affichées). J'ai Visual C++ Express 2008.

Alexandre.
Avatar
Jean-Marc Bourguet
AG writes:

On Mar 11, 4:18 pm, Jean-Marc Bourguet wrote:
> Tu peux essayer de donner un code minimal mais complet reproduisant le
> probleme?  (qu'est-ce que T ici par exemple).

Bonjour Jean-Marc.

Oui voilà mon code minimal qui compile, tourne, mais ne fonctionne
pas. Je remarque que les autres on répondu, donc je vais voir ce
qu'ils disent. mais en attendant voilà mon code, sans les const un peu
partout comme il a déjà été fait remarqué. Je regarde les autres
réponses.

#include <iostream>
#include <sstream>
#include <vector>
#include <string>

using namespace std;

template<class C> ostream & operator<<(ostream &o, vector<C> v);

class A
{
public:
template<class C>
string ValToString(C & in);
template<class C>
string ValToString(vector<C> & in);
};

int main(int argc, char * argv[])
{
A a;
int i=3;
vector<int> v;
v.push_back(1);
v.push_back(3);
v.push_back(4);
cout << "3 -> " << a.ValToString<int>(i) << "n";
cout << "{1,3,4} -> " << a.ValToString<vector<int> >(v);


cout << "{1,3,4} -> " << a.ValToString<int>(v);

Ton parametre template est int, pas vector<int> si tu veux la deuxieme
surcharge.

}

template<class C>
string A::ValToString(C &in)
{
ostringstream buff;
buff << in;
return buff.str();
}

template<class C>
string A::ValToString(std::vector<C> &in)
{
ostringstream buff;
buff << in;
return "(" + buff.str() + ")";
}

template<class C>
ostream & operator<<(ostream &o, vector<C> v)
{
vector<C>::iterator i;
for(i=v.begin();i!=v.end();++i)
{
o << *i << " ";
}
o << "n";
return o;
}



--
Jean-Marc
FAQ de fclc++: http://www.cmla.ens-cachan.fr/~dosreis/C++/FAQ
C++ FAQ Lite en VF: http://www.ifrance.com/jlecomte/c++/c++-faq-lite/index.html
Site de usenet-fr: http://www.usenet-fr.news.eu.org
Avatar
AG
On Mar 12, 11:21 am, Jean-Marc Bourguet wrote:
Ton parametre template est int, pas vector<int> si tu veux la deuxieme
surcharge.



well well well: ok, si je met <int> ça marche. indeed.

Mais je voudrais pouvoir utiliser ValToString<vector<int> >(v):

c'est pas possible ?

AG.
Avatar
Jean-Marc Bourguet
AG writes:

On Mar 12, 11:21 am, Jean-Marc Bourguet wrote:
> Ton parametre template est int, pas vector<int> si tu veux la deuxieme
> surcharge.

well well well: ok, si je met <int> ça marche. indeed.

Mais je voudrais pouvoir utiliser ValToString<vector<int> >(v):

c'est pas possible ?



Tu peux ne pas mettre de <> du tout: ValToString(v)

mais pour faire ce que tu veux, ce n'est plus de la surcharge mais de la
specialisation partielle qu'il faut et ce n'est possible qu'avec les
classes. Donc il faut faire intervenir une classe, par exemple dans
l'implementation de ValToString qui peut donc ne plus etre surchargee.

#include <iostream>
#include <sstream>
#include <vector>
#include <string>

using namespace std;

template<class C> ostream & operator<<(ostream &o, vector<C> v);

class A
{
public:
template<class C>
string ValToString(C& in);
};

int main(int argc, char * argv[])
{
A a;
int i=3;
vector<int> v;
v.push_back(1);
v.push_back(3);
v.push_back(4);
cout << "3 -> " << a.ValToString(i) << "n";
cout << "{1,3,4} -> " << a.ValToString(v);
}

template <class C>
struct B
{
B(C& v) : myC(v) {}
operator string() {
ostringstream buff;
buff << myC;
return buff.str();
}
C& myC;
};

template <class C>
struct B<vector<C> >
{
B(vector<C>& v) : myC(v) {}
operator string() {
ostringstream buff;
buff << myC;
return "(" + buff.str() + ")";

}
vector<C>& myC;
};

template<class C>
string A::ValToString(C& in)
{
return B<C>(in);
}

template<class C>
ostream & operator<<(ostream &o, vector<C> v)
{
typename vector<C>::iterator i;
for(i=v.begin();i!=v.end();++i)
{
o << *i << " ";
}
o << "n";
return o;
}

--
Jean-Marc
FAQ de fclc++: http://www.cmla.ens-cachan.fr/~dosreis/C++/FAQ
C++ FAQ Lite en VF: http://www.ifrance.com/jlecomte/c++/c++-faq-lite/index.html
Site de usenet-fr: http://www.usenet-fr.news.eu.org
1 2