void qsort (void* base, size_t num, size_t size,
int (*compare)(const void*,const void*));
Why does the qsort function want an int* return type for compare when the compare function is of type int?
int compare (const void * a, const void * b)
{
if ( *(MyType*)a < *(MyType*)b ) return -1;
if ( *(MyType*)a == *(MyType*)b ) return 0;
if ( *(MyType*)a > *(MyType*)b ) return 1;
}
Can someone explain this please, my program wont compile because of this. Thanks!
Code taken from this source:
http://www.cplusplus.com/reference/cstdlib/qsort/
It is not returning an int *, it is returning an int. compare is a function pointer. The * you are seeing there defines it as a function pointer. (Note the parentheses around *compare.)
cdecl parse of int (*compare)(const void*,const void*)):
declare compare as pointer to function (pointer to const void, pointer to const void) returning int
This would be the parameter declaration if it were a pointer to a function returning an int *:
int * (*compare)(const void*,const void*))
If your code is not compiling then it is for some other reason. Consider adding the error message to your question (or creating a new question) if you would like more specific advice about the compiler error.
Related
I wrote the piece of code below but when I tried to return some two-dimensional array, it throws the following error.
int (* function (int input[2][2]) ) [2][2]{
return input;
}
from trial and error, I understand that when I change the function declaration to int (* function (args) ) [2] {...} it works like a charm, but why??? I don't understand. How C++ actually sees arrays? How these return declarations int (* function () )[n][m] actually works? What happens when I add another * to function declaration int *(* function () )[n][m] ??
My source for finding the solution to this problem was this but I just copied some code and understood almost 0% of it.
It'll be nice if someone could explain to me how these work, and it would mean a world to me if you can suggest a good reading source for understanding these somewhat advanced notions in C++.
In this function declaration
int (* function (int input[2][2]) ) [2][2];
the argument of the array type is implicitly adjusted by the compiler to pointer to the array element type. That is for example these function declarations
int (* function (int input[2][2]) ) [2][2];
int (* function (int input[100][2]) ) [2][2];
int (* function (int input[][2]) ) [2][2];
declares the same one function that is equivalent to
int (* function (int ( *input )[2]) ) [2][2];
So within the function the variable input has the pointer type int ( * )[2]. This pointer you are returning from the function
return input;
So the function return type also must be int ( * )[2]. That means that the function must be declared like
int (* function (int input[2][2]) ) [2];
You could declare the parameter as having a referenced type. In this case you may return reference to the array.
int ( & function (int ( &input )[2][2]) )[2] [2];
Array types may not be used as the return type of function.
As for this declaration
int *(* function () )[n][m];
where n and m shall be constant expressions then the function returns pointer of the type int * ( * )[n][m]. For example the function can use an array name declared within the function with the static storage duration something in a return statement like
static int * a[k][n][m];
//
return a;
So if you have an array as for example
T a[N1][N2][N3];
where T is some type and N1, N2, and N3 its sizes then this declaration you may rewrite like
T ( a[N1] )[N2][N3];
Used in expressions the array (with rare exceptions) is converted to pointer to its first element. To declare such a pointer substitute the record in the parentheses to pointer like
T ( *p )[N2][N3] = a;
What does this error message mean?
error: call of overloaded ‘setval(int)’ is ambiguous
huge.cpp:18: note: candidates are: void huge::setval(unsigned int)
huge.cpp:28: note: void huge::setval(const char*)
My code looks like this:
#include <iostream>
#define BYTES 8
using namespace std ;
class huge {
private:
unsigned char data[BYTES];
public:
void setval(unsigned int);
void setval(const char *);
};
void huge::setval(unsigned int t) {
for(int i = 0; i< BYTES ; i++) {
data[i] = t;
t = t >> 1;
}
}
void huge::setval(const char *s) {
for(int i = 0; i< BYTES ; i++)
data[i] = s[i];
}
int main() {
huge p;
p.setval(0);
return 0;
}
The literal 0 has two meanings in C++.
On the one hand, it is an integer with the value 0.
On the other hand, it is a null-pointer constant.
As your setval function can accept either an int or a char*, the compiler can not decide which overload you meant.
The easiest solution is to just cast the 0 to the right type.
Another option is to ensure the int overload is preferred, for example by making the other one a template:
class huge
{
private:
unsigned char data[BYTES];
public:
void setval(unsigned int);
template <class T> void setval(const T *); // not implemented
template <> void setval(const char*);
};
The solution is very simple if we consider the type of the constant value, which should be "unsigned int" instead of "int".
Instead of:
setval(0)
Use:
setval(0u)
The suffix "u" tell the compiler this is a unsigned integer. Then, no conversion would be needed, and the call will be unambiguous.
replace p.setval(0); with the following.
const unsigned int param = 0;
p.setval(param);
That way it knows for sure which type the constant 0 is.
Use
p.setval(static_cast<const char *>(0));
or
p.setval(static_cast<unsigned int>(0));
As indicated by the error, the type of 0 is int. This can just as easily be cast to an unsigned int or a const char *. By making the cast manually, you are telling the compiler which overload you want.
Cast the value so the compiler knows which function to call:
p.setval(static_cast<const char *>( 0 ));
Note, that you have a segmentation fault in your code after you get it to compile (depending on which function you really wanted to call).
That is ambiguous because a pointer is just an address, so an int can also be treated as a pointer – 0 (an int) can be converted to unsigned int or char * equally easily.
The short answer is to call p.setval() with something that's unambiguously one of the types it's implemented for: unsigned int or char *. p.setval(0U), p.setval((unsigned int)0), and p.setval((char *)0) will all compile.
It's generally a good idea to stay out of this situation in the first place, though, by not defining overloaded functions with such similar types.
I have a working implementation of a avltree as a template class. I am adding two functions to this working implementation. These two functions that will transverse through the entire tree recursively and preform some calculations.
//avltree.cpp
//see comment in code below
template <class Comparable>
void AvlTree<Comparable>::transverseTree( AvlNode<Comparable> *t, const char *word, char matchingWords[100][MAX_LENGTH + 1], int *count) const
{
int distance;
if( t != NULL )
{
distance = levDistance(t->element/*avl word*/, word);
if (distance == 1)
{
*count++;
strcpy(matchingWords[*count], t->element/*avl word*/);
}
//error is here
transverseTree( t->left, word, matchingWords );
transverseTree( t->right, word, matchingWords );
}
}
//avltree.h
//new function
void transverseTree(AvlNode<Comparable> *t, const char *word, char matchingWords[100][MAX_LENGTH + 1],
int *count) const;
//new function
int levDistance(const char *str1, const char *str2) const;
When I try calling this function recursively, I receive this error message:
AvlTree.cpp:412:31: error: no matching function for call to ‘AvlTree<const char*>::transverseTree(AvlNode<const char*>*&, const char*&, char (*&)[34]) const’
transverseTree( t->left, word, matchingWords );
^
Why are their ampersands on the argument types to the recursive call? Are these references, and if so - how am I doing this?
You forgot to pass count in the recursive calls.
transverseTree( t->left, word, matchingWords, count ); // Missing count
transverseTree( t->right, word, matchingWords, count ); // Missing count
The signature looks like
void
AvlTree<Comparable>::transverseTree(AvlNode<Comparable> *t,
const char *word,
char matchingWords[100][MAX_LENGTH + 1],
int *count)
But your call looks like
transverseTree( t->right, word, matchingWords );
I think you forgot to pass the count pointer.
It probably has to do with your recursive calls not having the correct parameters.
void transverseTree(AvlNode<Comparable> *t, const char *word, char matchingWords[100][MAX_LENGTH + 1], int *count) const;
Here, when you declare this function, it takes in 4 parameters.
However, when you call this function recursively:
transverseTree( t->left, word, matchingWords );
You're forgetting about that last parameter *count, therefore that function you're trying to call is not defined with that particular function signature.
Ampersands don't matter here; they just allow passing an argument as a reference. Still, functions having non-reference arguments of the same type will also match (effectively requiring object copying before the function call) provided that there is a copy constructor defined (either explicitly or by default) for an argument type. In this case, the object type is a pointer, and a copy constructor is implicitly defined for it (merely copying the value). So there is no problem with that.
Still it seems the last argument, count , is missing in the recursive calls. It may be the cause of a compilation error (of course unless your have specified a default value for it in a declaration inside AvlTree class).
I am trying to create an inline function for a comparer to qsort - something like this:
function<int(int,int)> comparesort = [smarkers, emarkers, strSearch] (int *arg1, int *arg2) { return 0; };
qsort(sortptrs, nKeywords, sizeof(int), comparesort);
It's giving me this error
IntelliSense: no suitable conversion function from "std::tr1::function" to "int (__cdecl *)(const void *, const void *)" exists
ok - I changed it to this
auto comparesort = [sortptrs, smarkers, emarkers, strSearch] (int arg1, int arg2)
{
int a = 0;
.
.
.
return a;
};
std::sort(sortptrs, sortptrs + nKeywords, comparesort);
and it's giving an error:
error C3499: a lambda that has been specified to have a void return type cannot return a value
[edit on 7/30 3:55 pm]
I actually needed a pointer sort - I've got an array of start and end bytes of words (found in a string passed in from VB.Net managed code). I also have a pointer-array that contains "1,2,3..." and I needed to sort the pointer.
Didn't seem I could do that with std::sort so I implemented my own shell sort...
The signature of qsort takes a function pointer of type int(*)(const void*, const void*). You are trying to give it a function<int(int, int)>, which is not a function pointer, but an object encapsulating something (might be a function ptr, might be a functor) which is callable as int(int, int) (note that it wouldn't have the right signature, even if it was a function pointer).
qsort is a basically a legacy function for backward compatibility with c.
In c++ I would strongly suggest forgetting about it and using std::sort instead:
auto comparesort = [smarkers, emarkers, strSearch] (const int& arg1, const int& arg2) { return false; };
//directly store the lambda, avoiding the overhead of creating a `function<...>`
std::sort(sortptrs, sortptrs + nKeywords, comparesort);
qsort is the old C API that takes a function pointer directly. You can't use it with anything else such as lambdas. Instead, use std::sort.
What does this error message mean?
error: call of overloaded ‘setval(int)’ is ambiguous
huge.cpp:18: note: candidates are: void huge::setval(unsigned int)
huge.cpp:28: note: void huge::setval(const char*)
My code looks like this:
#include <iostream>
#define BYTES 8
using namespace std ;
class huge {
private:
unsigned char data[BYTES];
public:
void setval(unsigned int);
void setval(const char *);
};
void huge::setval(unsigned int t) {
for(int i = 0; i< BYTES ; i++) {
data[i] = t;
t = t >> 1;
}
}
void huge::setval(const char *s) {
for(int i = 0; i< BYTES ; i++)
data[i] = s[i];
}
int main() {
huge p;
p.setval(0);
return 0;
}
The literal 0 has two meanings in C++.
On the one hand, it is an integer with the value 0.
On the other hand, it is a null-pointer constant.
As your setval function can accept either an int or a char*, the compiler can not decide which overload you meant.
The easiest solution is to just cast the 0 to the right type.
Another option is to ensure the int overload is preferred, for example by making the other one a template:
class huge
{
private:
unsigned char data[BYTES];
public:
void setval(unsigned int);
template <class T> void setval(const T *); // not implemented
template <> void setval(const char*);
};
The solution is very simple if we consider the type of the constant value, which should be "unsigned int" instead of "int".
Instead of:
setval(0)
Use:
setval(0u)
The suffix "u" tell the compiler this is a unsigned integer. Then, no conversion would be needed, and the call will be unambiguous.
replace p.setval(0); with the following.
const unsigned int param = 0;
p.setval(param);
That way it knows for sure which type the constant 0 is.
Use
p.setval(static_cast<const char *>(0));
or
p.setval(static_cast<unsigned int>(0));
As indicated by the error, the type of 0 is int. This can just as easily be cast to an unsigned int or a const char *. By making the cast manually, you are telling the compiler which overload you want.
Cast the value so the compiler knows which function to call:
p.setval(static_cast<const char *>( 0 ));
Note, that you have a segmentation fault in your code after you get it to compile (depending on which function you really wanted to call).
That is ambiguous because a pointer is just an address, so an int can also be treated as a pointer – 0 (an int) can be converted to unsigned int or char * equally easily.
The short answer is to call p.setval() with something that's unambiguously one of the types it's implemented for: unsigned int or char *. p.setval(0U), p.setval((unsigned int)0), and p.setval((char *)0) will all compile.
It's generally a good idea to stay out of this situation in the first place, though, by not defining overloaded functions with such similar types.