2017-07-30 5 views
2

Essayer de comprendre pourquoi la déduction de type échoue ici avec un opérateur conditionnel.
Quelque chose dans la norme essayait d'empêcher la déduction de type dans ce cas? Tout pointeur pour comprendre cela serait génial.Fonctions récursives d'inférence de type C++

auto mfact(int i) 
{ 
    return (0==i) ? 1 : i * mfact(i-1); 
} 

auto mfact2(int i) 
{ 
    if (0 == i) 
     return 1; 

    else 
     return i * mfact2(i-1); 
} 
error: use of ‘auto mfact(int)’ before deduction of ‘auto’  
    return (0==i) ? 1 : i * mfact(i-1); 
+0

Vous devriez * au moins * publier votre message d'erreur du compilateur. Au mieux, postez un [mcve]. –

+0

Le type de retour est déduit une fois que tout le code dans la fonction a été examiné. Par conséquent, l'utilisation de la signature de fonction dans le code de la fonction est prématurée. Vous devrez indiquer le type de retour dans la déclaration. –

+0

@RichardHodges Le 'mfact2' ne peut pas être compilé si vous changez les conditions, en plaçant' return i * mfact2 (i-1); 'au-dessus de' return 1; '. Cela signifie-t-il que ce type est déduit par la première déclaration du compilateur? Testé avec GCC 7.1.1 –

Répondre

4

Le problème mfact est l'opérateur ternaire. La sémantique de cet opérateur spécifie que le type de l'expression est le type commun des deux sous-expressions conditionnelles (je paraphrase un bit).

Quel est le type commun? Pourquoi c'est int et ... Un type à déduire.
Ah, pas de problème! Quel est le type à déduire? C'est le type de l'opérateur ternaire ...

Nous avons un problème de poulet et d'oeuf. La définition de la fonction entière est mal formée car le type de l'expression ne peut pas être déterminé.

Qu'en est-il de mfact2? Il a deux déclarations de retour séparées. Le premier étant d'un entier simple. Comme une fonction ne peut avoir qu'un seul type de retour, la déduction de type de retour nécessite que les deux déclarations de retour ne soient pas en conflit.

Pour citer la révision de la norme 14 C++:

[dcl.spec.auto/2]

Le type d'espace réservé peut apparaître avec un déclarateur de fonction dans le décl-spécificateur-suivants, spécificateur-type-seq, conversion -function-id, ou trailing-return-type, dans tout contexte où un tel déclarateur est valide. Si le déclarateur de fonction inclut un type de retour arrière ([dcl.fct]), cela spécifie le type de retour déclaré de la fonction. Si le type de retour déclaré de la fonction contient un type d'espace réservé , le type de retour de la fonction est déduit du retour instructions dans le corps de la fonction, le cas échéant.

donc une instruction retour à déduire le type est suffisant, et:

[dcl.spec.auto/9]

Si une fonction avec un type de retour déclaré contenant un type espace réservé a plusieurs instructions de retour , le type de retour est déduit pour chaque déclaration de retour. Si le type déduit n'est pas le même dans chaque déduction , le programme est mal formé.

Dans ce cas simple, la première instruction doit être int et la seconde contient un appel récursif. Comme la même surcharge de fonction ne peut avoir qu'un seul type de retour, l'appel récursif doit également être de type int. Les deux déclarations de retour sont d'accord.