OVH Cloud OVH Cloud

Template et const_iterator

15 réponses
Avatar
Guillaume GOURDIN
Bonjour à tous,

je ne comprends pas pourquoi le code suivant ne compile pas :

template <class T>
bool Func_T(const vector<T> & sequence1, const vector<T> & sequence2)
{
vector<T>::const_iterator it1, it2;

// bla bla
}

int main(int argc, char ** argv)
{
vector<uint16_t> v1, v2;

Func_T(v1, v2);
}

Le message d'erreur de g++ est le suivant :

‘std::vector<T,std::allocator<_CharT> >::const_iterator’ is parsed as a
non-type, but instantiation yields a type
note: say ‘typename std::vector<T,std::allocator<_CharT>
>::const_iterator’ if a type is meant
In function ‘bool LiwCrcMatch_T(const std::vector<T,
std::allocator<_CharT> >&, const std::vector<T, std::allocator<_CharT>
>&) [with T = unsigned int]’:

Même en forcant le template est en appelant Func_T<uint16_t>(v1, v2),
j'ai la même erreur de compilatoin.

Quelqu'un aurait-il des éclaircissements?

Merci pour votre aide.

5 réponses

1 2
Avatar
Mickaël Wolff
Fabien LE LEZ a écrit :
On Wed, 25 Jun 2008 21:47:25 +0200, Mickaël Wolff
:

alors que j'aurais d'emblée apporté la modification
suivant :



Func_T<uint16_t>(v1, v2) ;



Pourquoi donc ?



Ben en fait je pensais à des problèmes de signature de fonction.
Visiblement, quelque chose m'échappe. Parce quen fait, dans ma tête,
Func_T(uint16_t,uint16_t) et Func_T<uint16_t>(T=uint16_t,T=uint16_t)
n'ont pas le même prototype. Mais en y réfléchissant bien, dans le
module compilé, il n'y a pas de trace que la fonction soit issue d'un
template ?

(D'ailleurs, l'OP a bien précisé que ça ne changeait rien au
problème.)



Arf, ça m'avait échappé.

--
Mickaël Wolff aka Lupus Michaelis
http://lupusmic.org
Avatar
James Kanze
On Jun 26, 4:07 am, Mickaël Wolff wrote:
Fabien LE LEZ a écrit :



> On Wed, 25 Jun 2008 21:47:25 +0200, Mickaël Wolff
> :



>> alors que j'aurais d'emblée apporté la modification
>> suivant :



>> Func_T<uint16_t>(v1, v2) ;



> Pourquoi donc ?



Ben en fait je pensais à des problèmes de signature de fonction.
Visiblement, quelque chose m'échappe. Parce quen fait, dans ma tête,
Func_T(uint16_t,uint16_t) et Func_T<uint16_t>(T=uint16_t,T=uint16_t)
n'ont pas le même prototype.



La définition de Func_T était :

template <class T>
bool Func_T(const vector<T> & sequence1, const vector<T> &
sequence2)
{
vector<T>::const_iterator it1, it2;

// bla bla

}

Quelque soit la spécialisation, ça ne pourrait jamais donner
Func_T( uint16_t, uint16_t ). Il l'a appelée avec deux
vector< uint16_t > ; la déduction de type trouve T égal
uint16_t, ce qui donne une signature de Func_T(
vector< uint16_t > const&, vector< uint16_t > const& ).

Mais en y réfléchissant bien, dans le module compilé, il n'y a
pas de trace que la fonction soit issue d'un template ?



Typiquement, si : il y a la décoration du nom qui l'indique, et
au moins avec les compilateurs dont j'ai l'habitude, il y a
aussi une différence dans la façon qu'elle soit déclarée dans le
fichier objet (lien dit faible, de façon à ce qu'en cas de
multiple définition, l'éditeur de liens en prend une au hazard,
plutôt que de la considérer comme une erreur). Mais ce qui se
trouve dans les fichiers objet, c'est bien la fonction qui
résulte de l'instantiation, et non le template même.

--
James Kanze (GABI Software) email:
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
Avatar
Mickaël Wolff
James Kanze a écrit :
La définition de Func_T était :

template <class T>
bool Func_T(const vector<T> & sequence1, const vector<T> &
sequence2)
{
vector<T>::const_iterator it1, it2;

// bla bla

}



Décidément, je n'ai pas les yeux en face des trous en ce moment.

Quelque soit la spécialisation, ça ne pourrait jamais donner
Func_T( uint16_t, uint16_t ). Il l'a appelée avec deux
vector< uint16_t > ; la déduction de type trouve T égal
uint16_t, ce qui donne une signature de Func_T(
vector< uint16_t > const&, vector< uint16_t > const& ).



En fait c'est d'un conflit éventuel entre Func_T<uint16_t>(vector<
uint16_t > const&, vector< uint16_t > const& ) et Func_T(vector<
uint16_t > const&, vector< uint16_t > const& ) auquel je voulais faire
allusion.

Typiquement, si : il y a la décoration du nom qui l'indique, et
au moins avec les compilateurs dont j'ai l'habitude,



Donc s'il y a un conflit entre une fonction « en dure » et une
fonction déclarée via un template, est-ce qu'il y a un choix normalisé,
ou c'est comme tu as dit au petit bonheur la chance ?

Merci encore pour vos réponses, malgré mon petit soucis d'attention :-D

--
Mickaël Wolff aka Lupus Michaelis
http://lupusmic.org
Avatar
Jean-Marc Desperrier
Mickaël Wolff wrote:
[...]
Donc s'il y a un conflit entre une fonction « en dure » et une
fonction déclarée via un template, est-ce qu'il y a un choix normalisé,
ou c'est comme tu as dit au petit bonheur la chance ?



Ils n'auront pas la même décoration, donc ne pourront être en conflit
pour le linker.
Avatar
James Kanze
On Jun 26, 10:54 am, Mickaël Wolff wrote:
James Kanze a écrit :



> La définition de Func_T était :



> template <class T>
> bool Func_T(const vector<T> & sequence1, const vector<T> &
> sequence2)
> {
> vector<T>::const_iterator it1, it2;
> // bla bla
> }



Décidément, je n'ai pas les yeux en face des trous en ce moment.



> Quelque soit la spécialisation, ça ne pourrait jamais donner
> Func_T( uint16_t, uint16_t ). Il l'a appelée avec deux
> vector< uint16_t > ; la déduction de type trouve T égal
> uint16_t, ce qui donne une signature de Func_T(
> vector< uint16_t > const&, vector< uint16_t > const& ).



En fait c'est d'un conflit éventuel entre Func_T<uint16_t>(vector<
uint16_t > const&, vector< uint16_t > const& ) et Func_T(vector<
uint16_t > const&, vector< uint16_t > const& ) auquel je voulais faire
allusion.



Quel conflit ? Ce sont les mêmes ; que tu spécifies
explicitement une spécialisation avec uint16_t, ou que le
compilateur le deduit, le resultat est le même : la
spécialisation avec uint16_t.

> Typiquement, si : il y a la décoration du nom qui l'indique, et
> au moins avec les compilateurs dont j'ai l'habitude,



Donc s'il y a un conflit entre une fonction « en dure » et une
fonction déclarée via un template, est-ce qu'il y a un choix normalis é,
ou c'est comme tu as dit au petit bonheur la chance ?



Le compilateur applique les règles de résolution de surcharge,
toujours. Et ces règles sont déterministes : ou bien, il y a
une seule « meilleur » fonction, bien déterminée par les
règles, ou bien, il y a ambiguïté, et c'est une erreur. Grosso
modo : le compilateur établit une liste des fonctions et des
templates de fonctions (qui ne sont pas encore des fonctions) à
considérer, selon les règles de la recherche des noms. Ensuite,
pour chacun des templates de fonction, il essaie d'en deduire
une spécialisation unique -- s'il y arrive, il remplace le
template de fonction par la spécialisation dans sa liste, sinon,
il l'écarte tout simplement. Puisque la spécialisation d'un
template de fonction est une fonction, le résultat, c'est qu'il
n'y a plus que des fonctions dans la liste. Alors, il applique
la résolution de surcharge pour en choisir une. À ce moment-là,
le fait que la fonction soit une spécialisation d'un template ou
non joue très peu -- seulement s'il y a ambiguïté entre une
fonction qui n'est pas une spécialisation et une qui l'est, le
compilateur choisi celle qui ne l'est pas, plutôt que de générer
une erreur.

En fait, les règles complètes sont d'une complexité inouïe, et à
mon avis, pas trop importantes, au moins que tu écrives un
compilateur. (S'il faut les comprendre en détail pour comprendre
le code, le code est trop subtile, et doit être simplifié.) Ce
qui est surtout important, c'est l'ordre des opérations
(récherche de nom, suivi de la spécialisation des templates,
avec déduction de type si nécessaire, suivi de la résolution du
surcharge). Et ensuite, quelque règles de base de la résolution
de surcharge, genre pas de conversion bat l'ajoute d'un const
bat une conversion standard bat une conversion définie par
l'utilisateur bat le passage par varargs, ou que chaque
paramètre est évalué isolement.

--
James Kanze (GABI Software) email:
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
1 2