Bonjour,
Je trouve que l'explication que tu donnes (bien que juste) donne une impression d'une règle avec plein d'exceptions, alors que la règle peut être exprimée de manière très générique avec moins d'exceptions.
La situation :
| template<class T>
void foo(P);
foo(e);
|
La première étape est de déterminer le type et la catégorie de e
, pour rester simple lvalue vs xvalue (j'oublie les prvalue volontairement) et le type est celui de l'objet désigné par e
(donc pas de référence).
Cas général : On retire l'éventuelle référence ou const/volatile
placé en premier à P
, par exemple :
P' const
devient P'
P'&
devient P'
P'&&
devient P'
P' const&
devient P' const
Ensuite on fait correspondre ce P
au type de e
Exceptions :
- Si
P
est de la forme T&&
et que e
est une lvalue, on ajoute une &
au type de e
. Ce cas est ton paragraphe références universelles (je ne suis pas convaincu qu'il soit nécessaire d’introduire ce terme d'ailleurs).
- Si
P
n'est pas de la forme P'&
ou P'&&
, on effectue une decay conversion ou on retire le const/volatile
placé en premier (au besoin) au type de e
. Ce cas est ton paragraphe passage par recopie.
Le dernier élément est que si un type U
est de la forme U'&
alors U&&
est identique à U'&
. C'est ce que tu as écris sous la forme :
Dans le cas d'une lvalue, T et ParamType sont déduits comme étant des lvalue-references. C'est le seul cas dans les règles de déduction des templates que T conserve sa référence. L'autre point surprenant est que bien que ParamType soit déclaré comme une rvalue (T && param), le compilateur en déduit que c'est une lvalue-reference.
Ce qui me gène dans la formulation que tu fais, c'est qu'il y a une impression que tout le processus de déduction change dans chaque cas, alors qu'il n'y a qu'une partie qui varie : selon la forme de P
on affecte le type de e
, la reste du processus est identique.
En particulier, dans ta formulation actuelle :
- Présenter le traitement des pointeurs comme une exception me gène, puisqu'elles ne sont pas traitées différemment d'un cas
std::vector<T>
;
- Précise que le cas référence universelle se produit uniquement dans le cas
T&&
et aucun autre (par exemple dans le cas T const &&
les règles sont les habituelles)
- La partie petite particularité de decltype ne traite pas le cas où
e
est une xvalue.
- Tu ne dis jamais (ou je l'ai raté) que la détermination de
T
est faite en cherchant le T
qui rend identique le type de e
et P
, alors que c'est pourtant la base (les subtilités étant les transformations à effectuer sur le type de e
et sur P
) de la déduction des paramètres template.