OVH Cloud OVH Cloud

Template et reference

6 réponses
Avatar
Marc Boyer
Bon, j'essaye de reprendre un code, qui ne compile pas,
pour diverses raisons.

A un moment, j'y ai
template <class C> int foo(C);
template <class C> int foo(C&);

Et dans la compilation, je me retrouve avec:
appel du surcharge foo(const Truc&);
est ambigue.
les candidats sont
foo(C)
foo(C&);

A première vue, j'aurais tendance à croire que toute
instantiation sera ambigue et à virer une des deux,
mais y a-t-il une subtilité qui m'aurait échappée ?

Marc Boyer
--
La contractualisation de la recherche, c'est me donner de l'argent pour
faire ce que je ne sais pas faire, que je fais donc mal, pendant que ce
que je sais faire, je le fais sans moyens...

6 réponses

Avatar
Loïc Joly
Marc Boyer wrote:

Bon, j'essaye de reprendre un code, qui ne compile pas,
pour diverses raisons.

A un moment, j'y ai
template <class C> int foo(C);
template <class C> int foo(C&);

Et dans la compilation, je me retrouve avec:
appel du surcharge foo(const Truc&);
est ambigue.
les candidats sont
foo(C)
foo(C&);

A première vue, j'aurais tendance à croire que toute
instantiation sera ambigue et à virer une des deux,
mais y a-t-il une subtilité qui m'aurait échappée ?


La règle est qu'en cas de possibilité d'obtenir deux fonctions templates
lors de la déduction des arguments template, lorsqu'il y a une
fonction plus spécialisée que l'autre (c'est à dire qu'à chaque fois
qu'elle peut être choisie, la première pourrait l'être aussi, mais non
réciproquement), alors l'ambiguïté est levée et c'est la plus
spécialisée qui gagne.

Donc, pour moi, ton compilateur devrait être content.

--
Loïc

Avatar
Arnaud Meurgues
Loïc Joly wrote:

template <class C> int foo(C);
template <class C> int foo(C&);
[...]


La règle est qu'en cas de possibilité d'obtenir deux fonctions templates
lors de la déduction des arguments template, lorsqu'il y a une fonction
plus spécialisée que l'autre (c'est à dire qu'à chaque fois qu'elle peut
être choisie, la première pourrait l'être aussi, mais non
réciproquement), alors l'ambiguïté est levée et c'est la plus
spécialisée qui gagne.

Donc, pour moi, ton compilateur devrait être content.


??? Quelle est la plus spécialisée qui devrait gagner ?

--
Arnaud
(Supprimez les geneurs pour me répondre)


Avatar
Marc Boyer
Loïc Joly wrote:
Marc Boyer wrote:
La règle est qu'en cas de possibilité d'obtenir deux fonctions templates
lors de la déduction des arguments template, lorsqu'il y a une
fonction plus spécialisée que l'autre (c'est à dire qu'à chaque fois
qu'elle peut être choisie, la première pourrait l'être aussi, mais non
réciproquement), alors l'ambiguïté est levée et c'est la plus
spécialisée qui gagne.

Donc, pour moi, ton compilateur devrait être content.


---- toto.cpp ---
template <class C> void foo(C c){c++;}
template <class C> void foo(C& c){c++;}

void bar(){
int i;
foo(i);
}
% g++ -ansi -Wall -pedantic -c toto.cpp
toto.cpp: In function `void bar()':
toto.cpp:8: error: call of overloaded `foo(int&)' is ambiguous
toto.cpp:3: note: candidates are: void foo(C) [with C = int]
toto.cpp:4: note: void foo(C&) [with C = int]


Marc Boyer
--
La contractualisation de la recherche, c'est me donner de l'argent pour
faire ce que je ne sais pas faire, que je fais donc mal, pendant que ce
que je sais faire, je le fais sans moyens...

Avatar
Loïc Joly
Marc Boyer wrote:

Loïc Joly wrote:

Marc Boyer wrote:
La règle est qu'en cas de possibilité d'obtenir deux fonctions templates
lors de la déduction des arguments template, lorsqu'il y a une
fonction plus spécialisée que l'autre (c'est à dire qu'à chaque fois
qu'elle peut être choisie, la première pourrait l'être aussi, mais non
réciproquement), alors l'ambiguïté est levée et c'est la plus
spécialisée qui gagne.

Donc, pour moi, ton compilateur devrait être content.



---- toto.cpp ---
template <class C> void foo(C c){c++;}
template <class C> void foo(C& c){c++;}

void bar(){
int i;
foo(i);
}
% g++ -ansi -Wall -pedantic -c toto.cpp
toto.cpp: In function `void bar()':
toto.cpp:8: error: call of overloaded `foo(int&)' is ambiguous
toto.cpp:3: note: candidates are: void foo(C) [with C = int]
toto.cpp:4: note: void foo(C&) [with C = int]


Et VC++ 2005 :
error C2668: 'foo' : ambiguous call to overloaded function
could be 'void foo<int>(C &)'
with
[
C=int
]
or 'void foo<int>(C)'
with
[
C=int
]
while trying to match the argument list '(int)'


Laissant tomber mon livre sur les templates, j'ai regardé la norme, et
j'y ai trouvé :

1 Template argument deduction is done by comparing each function
template parameter type (call it P) with the type of the corresponding
argument of the call (call it A) as described below.
2 If P is not a reference type:
— If A is an array type, the pointer type produced by the arraytopointer
standard conversion (4.2) is used in place of A for type deduction;
otherwise,
— If A is a function type, the pointer type produced by the
functiontopointer standard conversion (4.3) is used in place of A for
type deduction; otherwise,
— If A is a cvqualified type, the top level cvqualifiers of A’s type are
ignored for type deduction.
If P is a cvqualified type, the top level cvqualifiers of P’s type are
ignored for type deduction. If P is a reference type, the type referred
to by P is used for type deduction.

Ce qui semble en effet indiquer que dans ce cas, il n'y a pas de
différence entre les deux templates.

--
Loïc


Avatar
mmm
"Marc Boyer" wrote:
A un moment, j'y ai
template <class C> int foo(C);
template <class C> int foo(C&);

Et dans la compilation, je me retrouve avec:
appel du surcharge foo(const Truc&);
est ambigue.
les candidats sont
foo(C)
foo(C&);


Ptite idée comme ça : tout dépend de la gueule du code des fcts foo(...) et
des types possibles pour C,
par rapport à ce que je peux voir des protos et ptetre de l'idée qu'il
pourrait y avoir derrière (distinguer les appels avec des objets const et
des objets accessibles en rw, ou de rendre possible les 2):
La soluce serait de différencier les protos de la façon suivante:
template <class C> int foo(C); -> template <class C> int foo(const C&);
template <class C> int foo(C&); -> template <class C> int foo(C&);//idem

Avatar
Marc Boyer
=?windows-1252?Q?Loïc_Joly?= wrote:
Ce qui semble en effet indiquer que dans ce cas, il n'y a pas de
différence entre les deux templates.


Donc, c'est juste un truc qui compilera jamais...
C'est ça ?

Marc Boyer
--
La contractualisation de la recherche, c'est me donner de l'argent pour
faire ce que je ne sais pas faire, que je fais donc mal, pendant que ce
que je sais faire, je le fais sans moyens...