couldn't deduce template parameter ‘looptype’ - c++

#include<cstdlib>
#include<iostream>
#include<math.h>
#include<string>
using namespace std;
class getAverage{
public:
template<class add>
add computeAverage(add input[], int nosOfElem){
add sum = add();//calling default constructor to initialise it.
for(int index=0;index<=nosOfElem;++index){
sum += input[index];
}
return double(sum)/nosOfElem;
}
template<class looptype>
looptype* returnArray(int sizeOfArray){
looptype* inputArray= (int*)malloc(sizeof(int)*sizeOfArray);
for(int index=0;index<=sizeOfArray;++index){
inputArray[index]=index;//=rand() % sizeOfArray;
}
return inputArray;
}
};
int main(){
int sizeOfArray=2;
int inputArray;
getAverage gA;
int* x= gA.returnArray(sizeOfArray);
for(int index=0;index<=2;++index){
cout<<x[index];
}
cout<<endl;
cout<<gA.computeAverage(x,sizeOfArray);
free(x);
return 0;
}
I want to create a template function through which I can create dynamic arrays of different type(Int,long,string ..etc.). I tried doing it,and realised that the "looptype" never gets the type value. Can someone suggest a way to do this.
Thanks

template<class looptype>
looptype* returnArray(int sizeOfArray){
looptype* inputArray= (int*)malloc(sizeof(int)*sizeOfArray);
for(int index=0;index<=sizeOfArray;++index){
inputArray[index]=index;//=rand() % sizeOfArray;
}
return inputArray;
}
template parameters can only be deduced from the function-template arguments. Here the only argument your function template takes is sizeOfArray which is an int. How does the compiler know what typename looptype is? Since it cannot be deduced, you have to explicitly specify it.
int* x= gA.returnArray<int>(sizeOfArray);
rather than:
int* x= gA.returnArray(sizeOfArray);
BTW, what's the point of have a template parameter looptype when I know it can only be an int as sold by this line of your code:
...
looptype* inputArray= (int*)malloc(sizeof(int)*sizeOfArray);
...
Your use of malloc is scary. For virtually same performance, you are making simple tasks complicated. Prefer std::vector<int> or worse case std::unique_ptr<int[]>.

Related

Print value in array using template class-c++

Hi I'' trying to make a template for a class to print out values in an array.
#include<iostream>
using namespace std;
template <typename T>
class Array{
public:
Array(T array[], int arraysize){
size=arraysize;
_array=new T[size];
}
~Array(){
delete[] _array;
}
void print(){
for(int i=0; i<size; i++){
cout<<_array[i]<<' ';
}
}
private:
T *_array;
int size;
};
int main(){
int array1[5]={1,2,3,4,5};
Array<int> a(array1,5);
a.print();
float array2[5]={1.012, 2.324, 3.141, 4.221, 5.327};
Array<float> b(array2,5);
b.print();
string array3[]={"Ch1","Ch2","Ch3","Ch4","Ch5"};
Array<string> c(array3,5);
c.print();
return 0;
}
This is the code and I was wondering what's wrong because it would print out random numbers.
The code creates the template's class member _array using new, but does not initialize it to anything, and that's why you get random garbage printed out.
The constructor does receive a parameter array, and an initialized array is passed using that parameter. However, that parameter is completely ignored by the constructor, and nothing is done with it.
Your intent here, obviously, is to copy the contents of the array the template constructor receives, as an argument, into _array. But that code is missing.
The contents of the array parameter will not get copied into _array all by themselves. You have to write the code to do that.
Your constructor:
Array(T array[], int arraysize){
size=arraysize;
_array=new T[size];
}
All you did was to assign the Array's size and allocate memory without actually copying the contents. So all you see some random value for POD types, and default-constructed values for class types.
You should do the copying with std::copy
Array(T array[], int arraysize)
: _array(new T[arraysize]), size(arraysize)
{
std::copy(array, array+arraysize, _array);
}
As you can see, I used member initailizer list; Please remember the Rule of 5. Also, I advise you to use a std::unique_ptr instead.

template function to find subarray in C++

#include <iostream>
#include <string>
using namespace std;
template <class T> int IsSubArr(T& a, int a_len, T& b, int b_len)
{
int i,j;
bool found;
int k;
T& s=a,l=b;
int s_len = (a_len < b_len) ? a_len : b_len; // find the small array length
if (s_len == a_len) // check to set pointers to small and long array
{
s = a;
l = b;
}
else
{
s = b;
l = a;
}
for (i = 0; i <= a_len-s_len; i++) //loop on long array
{
found = true;
k=i;
for (j=0; j<s_len; j++) // loop on sub array
{
if (s[j] != l[i])
{
found = false;
break;
}
k++;
}
}
if (found)
return i;
else
return -1;
}
/******* main program to test templates ****/
int main()
{
int array[5] = {9,4,6,2,1};
int alen = 5;
int sub_arr[3] = {6,2,1};
int slen = 3;
int index= 0;
index = IsSubArr(array,alen,sub_arr,slen);
cout << "\n\n Place of sub array in long array: " << index;
cout << endl;
return 0;
}
for this line of code:
index = IsSubArr(array,alen,sub_arr,slen);
i get error:
Error 1 error C2782: 'int IsSubArr(T &,int,T &,int)' : template parameter 'T' is ambiguous
please help to resolve this issue ?
Since array[a] and array[b] where a != b are 2 different types, you'll need 2 type templates args.
A work around would be to use pointers.
+ template <class T> int IsSubArr(T* a, int a_len, T* b, int b_len)
+ T* s = a; T*l = b;
You defined the first and the third parameters as references
template <class T> int IsSubArr(T& a, int a_len, T& b, int b_len)
^^^^ ^^^^
and pass as arguments for these parameters two arrays with different types
int array[5] = {9,4,6,2,1};
int sub_arr[3] = {6,2,1};
//...
index = IsSubArr(array,alen,sub_arr,slen);
^^^^^ ^^^^^^^
The first argument has type int[5] and the third argument has type int[3]
So the compiler is unable to deduce the referenced type T.
If you are going to use arrays with the function then you could declare it like
template <class T, size_t N1, size_t N2>
int IsSubArr( T ( &a )[N1], T ( &b )[N2] );
Or you could use pointers instead of the references to arrays
template <class T> int IsSubArr( T *a, size_t a_len, T *b, size_t b_len );
Take into account that this declaration within the function
T& s=a,l=b;
is also wrong. It is equivalent to the following declarations
T& s=a;
T l=b;
That is the first declaration declares a reference to an array while the second declaration declares an array and tries to initialize it with another array. However arrays do not have a copy constructor and the compiler will issue one more error. And you may not reassign a reference.
You should know that there is standard algorithm std::search declared in header <algorithm> that can do the job you want to do with your function.
It's because array and sub_arr are two different types. array is of type int[5] while sub_arr is of type int[3]. The array dimensions are part of the type.
Either change the function to use two different templates arguments, one for each array, or use pointer (e.g. T*)
There's also another error, that you will continue to have if you keep using arrays and two different template arguments, and that is that you can't change references. Once you have assigned to the variable s and l in the function, those can't be made to reference anything else. The latter assignments of the s and l variables will fail because there you try to assign the arrays to each other, which you can not do, you can only copy arrays.
If you use pointers instead, then this won't be a problem.

what is wrong with the function parameter?

#include <iostream>
using namespace std;
template<class Type>
void Knapsack(Type *v,int *w,int c,int n,Type **m)
{
int i,j;
int jMax=max(w[n]-1,c);
for(j=0;j<=jMax;j++)
m[n][j]=0;
for(j=w[n];j<=c;j++)
m[n][j]=v[n];
for(i=n-1;i>1;i--)
{
for(j=0;j<=w[i]-1;j++)
m[i][j]=m[i+1][j];
for(j=w[i];j<=c;j++)
{
m[i][j]=max(m[i+1][j],m[i+1][j-w[i]]+v[i]);
}
}
m[1][c]=m[2][c];
if(c>=w[1])
m[1][c]=max(m[2][c],m[1][c-w[1]]+v[1]);
}
template <class Type>
void TrackBack(Type **m,int *w,int c,int n,int *x){
for(int i=1;i<=n;i++)
{
if(m[i][c]==m[i+1][c])
x[i]=0;
else
x[i]=1;
}
}
int main()
{
int m[101][101]={0};
int x[101];
int n=5;
int c=10;
int w[5]={2,2,6,5,4};
int v[5]={6,3,5,4,6};
Knapsack(v,w,c,n,m);
return 0;
}
I an writing the algorithm of 01 Knapsack problem.
my Xcode says "No matching function for call to 'Knapsack' "
I am stumbled by the red alarm.
I'm confused for passing arguments.
Is there anyone can help me? Thanks a lot:)
This is not a valid conversion:
int m[101][101]
...
Knapsack(v,w,c,n,m);
// ^-- expects a Type **m
m can decay to type "pointer to array of 101 ints", but no further.
At least type of argument
int m[101][101]={0};
is not equivalent to T ** where T is int.
When this array is passed by value as an argument it is implicitly converted to pointer to its first element and has type int ( * )[101]
Take into account that in any case this function is invalid. For example argument for second parameter w has 5 elements.
int w[5]={2,2,6,5,4};
The valid range of indices for it is [0,4]. n in the function call is equal to 5.
So this statement
int jMax=max(w[n]-1,c);
has undefined behaviour because you are using inadmissible index equal to 5.
template<class Type>
void Knapsack(Type *v,int *w,int c,int n,Type **m)
{
int i,j;
int jMax=max(w[n]-1,c);
//...
You a little bit wrong with definition of functions
template < class Type>
void Knapsack(Type *v,int *w,int c,int n,Type m[][101])
template < class Type>
void TrackBack(Type m[][101],int *w,int c,int n,int *x)

C++ Passing by pointer and passing by reference

#include<iostream>
using namespace std;
class A{
int *numbers[5];
public:
void assignment(int ** x){
for(int i=0;i<5;i++)
numbers[i]=x[i]; //not changing just the value of *numbers[i] but the pointer numbers[i]
}
void print(){
for(int i=0; i<5;i++)
cout<< *numbers[i]<<endl;
}
};
int main(){
int *x[5];
for(int i; i<5;i++){
x[i]= new int(i);
cout<<*x[i]<<endl;
}
cout<<endl;
A numbers;
numbers.assignment(x);
numbers.print();
return 0;
}
My question is very specific. I want to do the same thing as the code above but instead of passing the argument of function assignment(int **) by pointer to do it by reference. How can I achieve that?
Use:
void assignment(int* (&x)[5]) ...
edit: for the comment "if the length... wasn't standard...", you can use a template:
template<int N> void assignment(int* (&x)[N]) ...
The compiler will automatically deduce N.

Template & memory-allocation

#include <iostream>
template<class T> T CreateArray(T a, int n)
{
a = new T [n]; // mistake: double* = double**
return a;
}
int main()
{
double* a;
int n = 5;
a = CreateArray(a,n);
return 0;
}
can I allocate memory using a template and new? And what my mistake?
Your code has some wrong things. First, you can do something like what you're trying to do, but you should write something like this:
template<class T> T* CreateArray(int n)
{
T* a = new T [n];
return a;
}
int main()
{
double* a;
int n = 5;
a = CreateArray<double>(n);
return 0;
}
Note that you don't have to pass the a array (it will be copied inside CreateArray, and its changes won't be visible inside main). Note also that you define the template to returning a pointer T*, that is what main() a is expecting.
So others have explained why your code doesn’t work and how it can be improved.
Now I’ll show how you can still get the following code to compile – and to work properly:
double* a = CreateArray(5);
int* b = CreateArray(7);
The problem, as already mentioned, is that C++ does not infer template arguments from return types alone.
You can circumvent this limitation by making the above function return a simple proxy object. The proxy object has a single operation: an (implicit) conversion to T*. This is where the actual allocation happens.
The CreateArray function is therefore very simple (and not a template):
CreateArrayProxy CreateArray(std::size_t num_elements) {
return CreateArrayProxy(num_elements);
}
As for the proxy:
struct CreateArrayProxy {
std::size_t num_elements;
CreateArrayProxy(std::size_t num_elements) : num_elements(num_elements) { }
template <typename T>
operator T*() const {
return new T[num_elements];
}
};
Easy as π.
Now, should you use this code? No, probably not. It offers no real advantage over direct allocation. But it’s a useful idiom to know.
You want to accept a pointer to the type you want to allocate:
template<class T> T* CreateArray(T* a, int n)
{
a = new T [n];
return a;
}
This should do the trick.
I prefer to keep empty pointers value NULL.
#include <iostream>
template<class T> bool CreateArray(T * &a, int n)
{
if ( a != 0 )
return false;
a = new T [n];
return true;
}
int main()
{
double* a = 0;
int n = 5;
CreateArray(a,n);
return 0;
}
vector could be a good solution, too. I think it is better one, because you won't make memory leak(s).
#include <vector>
int main()
{
std::vector<double> a;
int n = 5;
a.resize(n);
return 0;
}