The error I get when compiling your code is as follows:
no matching function for call to ‘elevar(double, int&)’
return (n == 0) ? 0 : ((elevar(-1, n - 1)*elevar(x - 1, n)) / n) + ln1(x, n - 1);
~~~~~~^~~~~~~~~~
candidate: template<class T> T elevar(T, T)
T elevar(T x, T y) {
^~~~~~
note: template argument deduction/substitution failed:
note: deduced conflicting types for parameter ‘T’ (‘double’ and ‘int’)
return (n == 0) ? 0 : ((elevar(-1, n - 1)*elevar(x - 1, n)) / n) + ln1(x, n - 1);
~~~~~~^~~~~~~~~~
I will translate it in case it is not clear:
no existe ninguna función para llamar a ‘elevar(double, int&)’
return (n == 0) ? 0 : ((elevar(-1, n - 1)*elevar(x - 1, n)) / n) + ln1(x, n - 1);
~~~~~~^~~~~~~~~~
la candidata es: template<class T> T elevar(T, T)
T elevar(T x, T y) {
^~~~~~
note: la deducción/substitución del argumento de plantilla falló:
note: se dedujeron tipos diferentes para el parámetro ‘T’ (‘double’ e ‘int’)
return (n == 0) ? 0 : ((elevar(-1, n - 1)*elevar(x - 1, n)) / n) + ln1(x, n - 1);
~~~~~~^~~~~~~~~~
In detail:
-
There is no function to call
elevar(double, int&)
: The function that was deduced when instantiating the template is elevar(double, int&)
but there is no function with that signature. That means:
-
the deduction / substitution of the template argument failed : In the type deduction process, the types deducted for the template do not result in a valid function since ...
-
Different types were deducted for the parameter '
T
' ( double
e int
) : Your template elevar
has a template parameter ( T
) when instantiated with elevar(x - 1, n)
first expression is of type double
(since x
is double
) and deduces that the first parameter must be of that type, the second expression is n
that is of type int
and deduces that the second one parameter must be of that type ... but according to the signature of the template both parameters should be the same type, hence the conflict.
Solutions.
More types in the template.
If you allow your template to deduce different types, the problem disappears:
template<class T, class U>
// ~~~~~~~ <--- primer y segundo parámetro no tienen
// por qué ser del mismo tipo
T elevar(T x, U y) {
return (y == 0) ? 1 : x * elevar(x, y - 1);
}
Explain the type.
If you tell the template the type with which it will work, even if the second parameter is of a different type it will be converted (if there is possible conversion):
template<class T>
T ln1(T x, int n) {
return (n == 0) ? 0 : ((elevar<double>(-1, n - 1)*elevar<T>(x - 1, n)) / n) + ln1(x, n - 1);
// Los dos parámetros serán de tipo 'T' ---> ~~~
}
Add the function to the context.
If when replacing the parameters you find some function that matches the expected parameters, you will use it, so if you add a function with that signature in the context of use your program will compile:
double elevar(double x, int y) {
// ~~~~~~~~ ~~~~~ <--- No es plantilla, pero tiene la firma esperada
// se usará cuando se deduzca elevar(double, int)
return (y == 0) ? 1 : x * elevar(x, y - 1);
}