Does not recognize double-float templates

5

I have this code in which I try to approximate the natural logarithm of a number, but I can not use if , while or for , only the if ternario, but at the time it compiles I'm shot errors that T is ambiguous and that elevar has not been overloaded, but I do not understand why. (Only for numbers between 0 and 1.

I attach my code:

#include<iostream>
#include<cmath>
using namespace std;

template<class T> T ln1(T x, int n = 10);
template<class T> T ln2(T x, T e = 1e-8);
template<class T> T elevar(T x, T y);

int main() {

    cout << ln1((double)0.5, 500) << endl;

    system("pause");
    return 0;
}


template<class T>
T elevar(T x, T y) {
    return (y == 0) ? 1 : x * elevar(x, y - 1);
}

template<class T>
T ln1(T x, int n) {
    return (n == 0) ? 0 : ((elevar(-1, n - 1)*elevar(x - 1, n)) / n) + ln1(x, n - 1);
} 

PS: I use the conversion to test.

    
asked by TheAndreyx22 27.09.2018 в 04:21
source

3 answers

4

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);
}
    
answered by 27.09.2018 / 08:13
source
3

If we execute your program, we get

  

In instantiation of 'T ln1 (T, int) [with T = double]':
  error: no matching function for call to 'raise (double, int & amp))'

Which is pretty clear: you're calling your elevar( ) function with 2 different types , when you've declared it to use 2 parameters of the same type .

Since I do not know the logic of the mathematical operations you are using, I can not give you a solution. But, as you have it, or change your calls to elevar( ) to use 2 arguments of the same type, or change the function elevar( ) to work with 2 different types.

    
answered by 27.09.2018 в 05:38
3

The error is already telling you @Trauma .

We go with the possible solutions:

The simplest thing is to modify elevar so that the second parameter is a int , since it is the only use you give in your code:

template<class T> T elevar(T x, int y);

// ...

template<class T>
T elevar(T x, int y) {
    return (y == 0) ? 1 : x * elevar(x, y - 1);
}

Another option is to use two different abstract types in the function:

template<class T, class U> T elevar(T x, U y);

// ...

template<class T, class U>
T elevar(T x, U y) {
    return (y == 0) ? 1 : x * elevar(x, y - 1);
}

In practice the result is exactly the same, but for simplicity and readability I would apply the first solution.

    
answered by 27.09.2018 в 08:00