I am getting this error and another error too ** "IntelliSense: no instance of function template matches the argument list"** when compiling the following code
I know there might be logic mistakes in my function but I need to solve this error first to be able to debug my function .
#include <iostream>
using namespace std;
template<class T>
T myMax (T& arr ,int arrStart ,int arrSize)
{
if(arrStart==arrSize-1)
return arr[arrSize];
int median = (arrStart+arrSize)/2 ;
T left , right , maximum ;
left = max(arr,arrStart , median);
right = max(arr , median+1 , arrSize-1) ;
if (left>right)
maximum = left;
else
maximum = right ;
return maximum ;
}
void main()
{
int arrSize = 5;
int arr[] = {1,3,4,6,22};
int x;
x = myMax(arr,0,arrSize);
}
The argument for parameter arr is of type int[5]. Since you didn't specify a template argument for T when calling myMax, argument deduction happens and T is deduced to be int[5].
Then the compiler attempts to specialize the function template with T = int[5] (i.e., it tries to replace all instances of T with int[5]). This fails because the function returns a T by value but it is not possible to return an array (like int[5]) by value.
It looks like you want T to be the element type. If that is the case, you can explicitly take a reference to the array, e.g.,
template<class T, unsigned N>
T myMax (T (&arr)[N])
Though, a more idiomatic way to write the function would be to have it take a pair of random access iterators and have it return an iterator pointing to the "max" element:
template <typename RandomAccessIt>
RandomAccessIt myMax (RandomAccessIt first, RandomAccessIt last)
first is an iterator to the first element in the range and last is an iterator to one-past-the-end of the range, as is idiomatic for the STL algorithms. Pointers are usable as random access iterators, so this function can be called as
int* pointerToMaxElement = myMax(arr, arr + arrSize);
The advantage of the iterator approach is that it works with any random access range, including an array, std::vector, std::array, and std::deque.
From a quick look, the two things that jump out at me are:
You're using T in different ways in the template function. You're returning a T object, and taking a reference to a T object as an argument - but when you use it, you're passing an an int array as the argument but expect just an int returned
You don't call your template function with any template (ie, myMax<int>(...)) Edit - as Mark B points out, this isn't required however
Related
I am trying to write a function that prints out the elements in an array. However when I work with the arrays that are passed, I don't know how to iterate over the array.
void
print_array(int* b)
{
int sizeof_b = sizeof(b) / sizeof(b[0]);
int i;
for (i = 0; i < sizeof_b; i++)
{
printf("%d", b[i]);
}
}
What is the best way to do iterate over the passed array?
You need to also pass the size of the array to the function.
When you pass in the array to your function, you are really passing in the address of the first element in that array. So the pointer is only pointing to the first element once inside your function.
Since memory in the array is continuous though, you can still use pointer arithmetic such as (b+1) to point to the second element or equivalently b[1]
void print_array(int* b, int num_elements)
{
for (int i = 0; i < num_elements; i++)
{
printf("%d", b[i]);
}
}
This trick only works with arrays not pointers:
sizeof(b) / sizeof(b[0])
... and arrays are not the same as pointers.
Why don't you use function templates for this (C++)?
template<class T, int N> void f(T (&r)[N]){
}
int main(){
int buf[10];
f(buf);
}
EDIT 2:
The qn now appears to have C tag and the C++ tag is removed.
For C, you have to pass the length (number of elements)of the array.
For C++, you can pass the length, BUT, if you have access to C++0x, BETTER is to use std::array. See here and here. It carries the length, and provides check for out-of-bound if you access elements using the at() member function.
In C99, you can require that an array an array has at least n elements thusly:
void print_array(int b[static n]);
6.7.5.3.7: A declaration of a parameter as ‘‘array of type’’ shall be adjusted to ‘‘qualified pointer to
type’’, where the type qualifiers (if any) are those specified within the [ and ] of the
array type derivation. If the keyword static also appears within the [ and ] of the
array type derivation, then for each call to the function, the value of the corresponding
actual argument shall provide access to the first element of an array with at least as many
elements as specified by the size expression.
In GCC you can pass the size of an array implicitly like this:
void print_array(int n, int b[n]);
You could try this...
#include <cstdio>
void
print_array(int b[], size_t N)
{
for (int i = 0; i < N; ++i)
printf("%d ", b[i]);
printf("\n");
}
template <size_t N>
inline void
print_array(int (&b)[N])
{
// could have loop here, but inline forwarding to
// single function eliminates code bloat...
print_array(b, N);
}
int main()
{
int a[] = { 1, 2 };
int b[] = { };
int c[] = { 1, 2, 3, 4, 5 };
print_array(a);
// print_array(b);
print_array(c);
}
...interestingly b doesn't work...
array_size.cc: In function `int main()':
array_size.cc:19: error: no matching function for call to `print_array(int[0u])'
JoshD points out in comments below the issue re 0 sized arrays (a GCC extension), and the size inference above.
In c++ you can also use a some type of list class implemented as an array with a size method or as a struct with a size member(in c or c++).
Use variable to pass the size of array.
int sizeof_b = sizeof(b) / sizeof(b[0]); does nothing but getting the pre-declared array size, which is known, and you could have passed it as an argument; for instance, void print_array(int*b, int size). size could be the user-defined size too.
int sizeof_b = sizeof(b) / sizeof(b[0]); will cause redundant iteration when the number of elements is less than the pre-declared array-size.
The question has already some good answers, for example the second one. However there is a lack of explanation so I would like to extend the sample and explain it:
Using template and template parameters and in this case None-Type Template parameters makes it possible to get the size of a fixed array with any type.
Assume you have such a function template:
template<typename T, int S>
int getSizeOfArray(T (&arr)[S]) {
return S;
}
The template is clearly for any type(here T) and a fixed integer(S).
The function as you see takes a reference to an array of S objects of type T, as you know in C++ you cannot pass arrays to functions by value but by reference so the function has to take a reference.
Now if u use it like this:
int i_arr[] = { 3, 8, 90, -1 };
std::cout << "number f elements in Array: " << getSizeOfArray(i_arr) << std::endl;
The compiler will implicitly instantiate the template function and detect the arguments, so the S here is 4 which is returned and printed to output.
So I am currently learning C++ (with previous experience in Java and JavaScript) and as far as I am concerned you can't pass an array as argument in C++ like you can in Java. But you can pass a pointer to the first element in the array. So I could iterate through an array like this:
bool occurs(int* arrInt, int length, int sought, int& occurrences)
{
for (int i = 0; i <= length; ++i)
{
if (arrInt[i] == sought)
occurrences++;
}
// if occurences > 0 return true, else false
return occurrences;
}
The whole function should basically return a boolean telling me wether the given int (sought) was found in the array (arrInt) or not. Also I am supplying a little counter via reference (occurrences).
But what bugs me is the length parameter. C++11 provides those fancy std::begin / cbegin() and std::end / cend() functions to get the first and one past the last element of an array:
int arr[] = {1,2,3,4} // arr is basically a pointer to an int, just as the
// function parameter of ocurs(int*,int,int,int&)
auto end = std::end(arr); // end points to one past last element
But why can't I use my arrInt parameter as argument for that function? Then i could get rid of the length parameter:
bool occurs(int* arrInt, int sought, int& occurences)
{
for (auto it = std::begin(arrInt); it != std::end(arrInt); ++it)
{
if (*it == sought)
occurences++;
}
// if occurences > 0 return true, else false
return occurences;
}
Am I missing a major concept here? Thanks in advance
In your first example:
int arr[] = {1,2,3,4} // arr is basically a pointer to an int, just as the
// function parameter of ocurs(int*,int,int,int&)
auto end = std::end(arr); // end points to one past last element
arr is NOT "basically a pointer to an int". arr is of type int[4]. Note that the length is part of the type. As a result, the compiler can easily determine where "one past last element" is. Just add the length.
Where the confusion may come in is that arr is convertible to (you'll sometimes hear decays to) int*. But it isn't just a pointer.
In your second example:
bool occurs(int* arrInt, int sought, int& occurences)
{
for (auto it = std::begin(arrInt); it != std::end(arrInt); ++it) {
...
}
...
}
arrInt is just a pointer. As such, how can you know where end() is? There's no information here. That's why you need that extra length parameter.
You can instead pass in the full array, but you have to do it by reference (you cannot pass arrays by value, thanks C!). And to do that, you have to make it a function template:
template <size_t N>
bool occurs (int (&arrInt)[N], int sought, int& occurrences) {
...
}
Here, arrInt is an array - and its length is encoded in the type (N). So you can write std::end(arrInt).
occurs() is basically rewriting std::count, so you could just use that instead:
int arr[] = {1, 2, 3, 3, 8};
int occurrences = std::count(std::begin(arr), std::end(arr), 3); // yields 2
Or, even simpler, use std::vector<int>.
First, note that an array is not a pointer. And so in this example code:
int arr[] = {1,2,3,4} // arr is basically a pointer to an int, just as the
// function parameter of ocurs(int*,int,int,int&)
… the comments are simply wrong.
However, in both C and C++ an array type expression decays to pointer type, with pointer to first item as result, in a context where a pointer is expected. An example that is not such context, is where an array is passed by reference. Another example is when it's used as argument to sizeof.
With arrInt declared as
int* arrInt
it's just a pointer, with no information about whether it points to a single int or to somewhere in an array, and so
std::end(arrInt)
can't deduce an array size. Normally it deduces that from the array type of the argument. Or from a container's size or end member (how it's implemented is unspecified, and the same info is available several ways).
One possibility is to change your function design, e.g. change it to accept two pointers (or general iterators), like std::find.
Another possibility is to use std::find in your function.
You can do that because given a start pointer and an array size, you can trivially compute the past-the-end pointer for the array, to use as argument to std::find.
Here is my problem:
I have a struct:
struct point
{
int x;
int y;
};
and then I have an array:
for (int i = 0;i < n;i++)
{
arr[i].x=rand() % n + 1;
}
I defined the quicksort function as follows:
void quicksort(int *a, int left, int right);
and I want to sort the point by X coordinate, so I call the quicksort:
quicksort(arr.x, 0, n-1);
And this is the error message:
error: request for member 'x' in 'arr', which is of non-class type 'point [(((unsigned int)(((int)n) + -0x000000001)) + 1)]'
Sorry if the question is too stupid or badly formulated, the truth is I'm a newbie and I'm really willing to learn as much as possible and I'd be very thankful for your help!
If you always want to sort by x, then you can hard-code it into the sort function, and just pass a pointer to the array to sort:
void quicksort(point * arr, int left, int right) {
// test points with
// if (arr[i].x < arr[j].x) {/* i sorts before j */}
}
quicksort(arr, 0, n-1);
To specify a class member to sort by, you need a pointer-to-member, not a pointer; something like:
void quicksort(point * arr, int point::*member, int left, int right){
// test points with
// if (arr[i].*member < arr[j].*member) {/* i sorts before j */}
}
quicksort(arr, &point::x, 0, n-1);
More generically, you could follow the example of std::sort and accept any comparison functor:
template <typename RandIter, typename Compare>
void quicksort(RandIter begin, RandIter end, Compare compare) {
// test points with
// if (compare(*it1, *it2)) {/* *it1 sorts before *it2 */}
}
quicksort(arr, arr+n,
[](point const &lhs, point const &rhs) {return lhs.x < rhs.x;});
And of course, unless you're learning how to implement a sorting algorithm, just use std::sort.
quicksort(arr,0,n-1);
then within quicksort, try to compare the arr[i].x
There are a few problems with your code.
1. quicksort accepts int* but you try to pass int value x
2. You try to pass int but you actually call an undefined variable arr.x
What you need to do is either call in the form of &arr[i].x, but to accomplish what you want, you probably want to pass the entire struct as a pointer.
You need to pass arr as the parameter, as that is the array to be sorted. arr.x is meaningless. You are not passing the string "arr.x" as a parameter which can somehow be interpreted as meaning sort on the x field - when the compiler sees this, it is looking for an x element of arr, which doesn't exist, as the error message suggests - only the elements of arr (e.g. arr[0]) have x elements (accessed as arr[0].x).
Assuming this is for academic purposes (why else would you declare your own sorting algorithm instead of using one of the ones already implemented with a custom comparator?), you can do this a few ways:
Array
std::array<point, 10> myArray; // declares an array of size 10 for points
template<size_t N>
void quicksort(std::array<point, N>& arr, ...)
{
// implement sort operating on arr
}
Vector
std::vector<point> myVector; // declares a dynamic array/vector of points
void quicksort(std::vector<point>& arr, ...)
{
// implement sort operating on arr
}
If for some god-awful reason, you want to keep it in C:
Legacy
const size_t SIZE = 10;
point arr[SIZE]; // declare an array of 10 points
void quicksort(point* p, const size_t n, ...)
{
// implement sort operating on elements in p passing in SIZE for n
}
I'd rather defined the function as:
void quicksort(void *a,int left,int right, size_t size, int (*fp)(void*,void*));
size is the size of one element of array and fp is a compare function which returns true if the two arguments are equal. Now you can pass the call the function as:
quicksort(arr,0,n-1,sizeof(arr)/sizeof(arr[0]), compare);
where function compare is something like:
int compare(void* a, void* b) { return *((int*)a) >= *((int*)b); }
Rest of the implementation of function is trivial I think.
(almost) never try to fool the system by passing a pointer to a member when you really want to pass a pointer to an object. Do as Grijesh suggested. Passing a member can lead to horrible side effects. For example, quicksort is going to sort all the integers together, regardless of which of them are X's and which are Y's. In milder cases you may get wrong compare criteria, and often hard to debug effects such as incorrect pointer optimization. Just be honest with the compiler and pass the object pointer if you need to pass an object pointer. There are very very very few exceptions, mostly to do with low-level system programming where the "other side' of the function call won't be able to handle the object.
I'm trying to write a function for enumerating through a number of a specific base, where the number is stored in some kind of list. Here is an example, taking a std::vector
void next_value(std::vector<unsigned int> &num, unsigned int base) {
unsigned int carry = 1;
for (unsigned int &n: num) {
n += carry;
if (n >= base) {
carry = 1;
n = 0;
} else {
carry = 0;
}
}
}
The num vector doesn't necessarily need to be a vector, it can be an array, or actually any type that has a std::begin() and std::end() defined for it. Is there a way to express that num can be anything with begin() and end(), but that it must have unsigned int type for its elements?
If you really want to check this, try:
template <class Sequence>
void next_value(Sequence &num, unsigned int base) {
static_assert(boost::is_same<Sequence::value_type, unsigned>::value, "foo");
// ...
If you're not using C++11 yet, use BOOST_STATIC_ASSERT instead.
If you need to support plain C-style arrays, a bit more work is needed.
On the other hand, #IgorTandetnik correctly points out that you probably do not need to explicitly check at all. The compiler will give you an (ugly) error if you pass a type which is truly unusable.
Writing a generic function with a static_assert is a good idea, because you can give the user a helpful error message rather than "foo".
However there is another approach using C++11:
template <typename Container, typename ValueType>
typename std::enable_if<std::is_same<Container::value_type, ValueType>::value, void>::type
next_value(Container& num, ValueType base)
{
// ...
}
This is a rather cryptic approach if you've never seen this before. This uses "Substitution failure is not an error" (SFINAE for short). If the ValueType doesn't match the Container::value_type, this template does not form a valid function definition and is therefore ignored. The compiler behaves as if there is not such function. I.e., the user can't use the function with an invalid combination of Container and ValueType.
Note that I do recommend using the static_assert! If you put a reasonable error message there, the user will thank you a thousand times.
I would not in your case.
Change carry to a book, use ++ instead of +=, make base a type T, and n an auto&.
Finally, return carry.
Your code now ducktypes exactly the requirements.
If you want diagnostics, static assert that the operations make sense with custom error messages.
This let's your code handle unsigned ints, polynomials, bigints, whatever.
I have tried to create a template function that does some weighted sampling within a Monte Carlo simulation. It is below. input_data will either be a statically-allocated array (i.e. data[33]), a dynamically-allocated array, or a vector.
template <class myType>
int init_roulette_calcs(myType &input_data, int inputlength, int *(&output_cdf), int highclassix, int weight)
{
sort(input_data, input_data + inputlength); //where the error occurs
//other code:
output_cdf = new int [inputlength];
int k = 1;
for (int i = 0; i < inputlength; i++)
{
output_cdf[i] = k;
if (i+1 < highclassix) k++;
else k += weight;
}
return output_cdf[inputlength-1];
}
The code will not compile because the template function could not deduce the argument for the call to sort. This may be a stupid question, but what do I need to do to ensure that sort can work properly?
Error 4 error C2784: 'std::_Vb_iterator<_Alloc> std::operator
+(_Alloc::difference_type,std::_Vb_iterator<_Alloc>)' : could not deduce template argument for
'std::_Vb_iterator<_Alloc>' from 'int' j:\rdm\lrgv_2011-07-21\lrgv_src\lrgv.h 398
Thanks in advance for your help.
If you put in an array, the array name is essentially a pointer to the first element, and the array name + x is the poitner to the xth element - so you have this part correct.
The problem is that this is not the case for a vector, which is why you need to use the .begin() and .end() functions to get the pointer to these locations.
You could try sorting by pulling the addresses of the dereferenced start/end elements - that might let you treat a vector the same as an array.
In your code, input_data is a reference, but sort would need it to be a pointer to the start of an array. It should be:
int init_roulette_calcs(myType input_data[], int inputlength, …
Although it would be proper STL usage to make such a template that the user can provide any kind of random access begin and end iterators instead. Thus you could later switch to a vector or any other container that sort can work on…
template <class InputIterator>
int init_roulette_calcs(InputIterator begin, InputIterator end, int *(&output_cdf), int highclassix, int weight)
sort(&input_data, &input_data + inputlength);
^^^ ^^^
I hope the argument you're passing is actually a reference to the first element in an array.