Reputation: 29
I'm pretty new in C++. I'm working on a school assignment that requires to use a function template to find the maximum value of an array. The code seemed to work fine with normal functions until I changed it to a function template. I now receive an error:
maxcpp.cpp:9:16: error: indirection requires pointer operand ('int' invalid)
return *myArr[first];
Not quite sure what happened there but any help would be appreciated.
Here is the source code:
template <typename T>
T maxArray(T myArr, int first, int last){
if(first == last){
return myArr[first];
}
else
{
int mid = first + (last-first)/2;
return(std::max(maxArray(myArr,first,mid),maxArray(myArr,mid+1,last)));
}
}
int main(){
int array1[] = {5,20,3,1};
std::cout << maxArray(array1,0,4) << std::endl;
return 0;
}
Upvotes: 1
Views: 304
Reputation: 12749
This is a due to the template argument deduction rules.
Given the following lines of code
int arr[] = {1, 2, 3, 4, 5};
auto x = func(arr);
The deduced types (of the argument and the return value) depend on how the function is declared.
OP's definition is similar to this
template <typename T> T func(T arg) {
return *arg; // <-- Error
};
Where T
is deduced as an int *
(the arrray decays to a pointer when passed to the function) and so is the type of arg
. This leads to an error, beeing *arg
an int
, while the declared return type of this function should be an int *
.
An option, as already noted, could be to change the signature into something like this
template <typename T> T func(T* arg) {
return *arg; // ^^
};
Where T
is deduced as int
, while arg
has type int *
.
Another option, would be the following:
template <typename T, std::size_t N> T func(T (&arg)[N]);
// ^^^^^^^^^^^^^ ^^^^^^^^^^^
Where the function accepts a reference to an array (in my example arg
is deduced as a reference to an int[5]
, the array doesn't decay to an int *
inside the function). Note that the size of the original array is also accessible by the function as the non-type template parameter N
.
As a proof of concept, this could be an alternative implementation of OP's program:
#include <iostream>
template <typename T>
T max_in_array_impl(T const* first, T const* last)
{ // ^^^^^^^^^^^^^^
if ( first + 1 == last) {
return *first;
}
else
{
T const* mid = first + (last - first) / 2;
return std::max(max_in_array_impl(first, mid),
max_in_array_impl(mid, last));
}
}
template <typename T, std::size_t N>
T max_in_array(T const(&arr)[N])
{ // ^^^^^^^^^^^^^^^^^ arr is a reference of an array of N const elements of type N
return max_in_array_impl(arr, arr + N);
// ^^^ here decays to a pointer
}
int main()
{
int array[] = {1, -35, 20, 24, 13};
std::cout << max_in_array(array) << '\n';
}
Testable here.
Upvotes: 0
Reputation: 1226
I guess using a recursive algorithm is also part of your assignment? Otherwise you can simply write (fixes in the comments are already applied):
#include<algorithm>
#include<iostream>
template <typename T>
T maxArray(T* myArr, int first, int last){
return *(std::max_element(myArr+first,myArr+last+1));
}
int main(){
int array1[] = {5,20,3,1};
std::cout << maxArray(array1,0,3) << std::endl;
return 0;
}
Here's a live example.
Upvotes: 0
Reputation: 9682
You could change the argument type along these lines:
template <typename T>
T maxArray(const std::vector<T>& myArr, int first, int last){
if(first == last)
{
return myArr[first];
}
else
{
int mid = first + (last-first)/2;
return(std::max(maxArray(myArr,first,mid),maxArray(myArr,mid+1,last)));
}
}
Upvotes: 2