c++ function taking function pointer with a default function - c++

assume I have the following function
int watchVar(const char* var, const char* descriptor,
Color (*colorfunc)(const char* var) = yellowColorFunc)
with
Color yellowColorFunc(const void* var){
return Color::yellow();
}
I want to overload watchVar to accept functions whos parameters are char, int, float, etc, but do not want to create a default color function for each type.
g++ gives this error:
xpcc::glcd::Color (*)(const char*)' has type 'xpcc::glcd::Color(const void*)
Is there another way besides declaring colorfunc to take a void pointer and forcing the caller to cast the argument later himself?
Thanks

the function pointer is declared const char * but the yellowColorFunc is declared const void *

Your problem is that your declaring a function pointer taking a const char * but yellowColorFun takes a const void *. If c++11 is available you can use std::function like so:
auto colorFunc = std::function<int(const char *,const char *,std::function<Color(const char*)>)>();
You said in a comment that you wanted to use the function for int,float and others, what your should do in that situation is use a templated function, you really don't wanna use void*'s in c++ very often.

Related

How can I make my strchr function take both 'const char' and 'char' arrays as first parameter?

I am expecting my function to work just the same as the function "strchr" I am using from the cstring / string.h library.
I understand that I cannot cast a " const char* " variable / array to " char* ". Yet, how is the predefined "strchr" function able to be passed both "const char" and "char" data type arrays and work just fine ? How could I change mine so that it works, too ?
char* my_strchr(char *place_to_find, char what_to_find)
{
for(int i=0;place_to_find[i];i++)
if(what_to_find==place_to_find[i]) return place_to_find+i;
return NULL;
}
...
int main()
{
const char vocals1[]="AEIOUaeiou";
char vocals2[]="AEIOUaeiou";
cout<<strchr(vocals1,'e');
cout<<strchr(vocals2,'e');
cout<<my_strchr(vocals1,'e');
cout<<my_strchr(vocals2,'e');
return 0;
}
As you could probably already tell, my third cout<< does not work.
I am looking for a way to change my function ( I am guessing the first parameter should somehow be typecast ).
How can I make my strchr function take both 'const char' and 'char' arrays as first parameter?
You could change the argument to be const char*. That would allow passing both pointers to char as well as const char.
However, you return a non-const pointer to that array, which you shouldn't do if the pointer is to a const array. So, when passing a const char*, your function should also return const char*
Yet, how is the predefined "strchr" function able to be passed both "const char" and "char" data type arrays and work just fine ?
There are two predefined std::strchr functions. One that accepts and returns char* and another that accepts and returns const char*:
const char* strchr(const char* str, int ch);
char* strchr( char* str, int ch);
If you would wish to return char* in case of char* argument, you need to have a different function for each case, like the standard library has. You can use an overload like the standard library does, or you can use a function template to generate both variations without repetition:
template<class Char>
Char* my_strchr(Char *place_to_find, char what_to_find)
Note that the C version of the function is declared char *strchr(const char *str, int ch). This makes the single function usable in both cases, but is unsafe, since the type system won't be able to prevent the user of the function from modifying though the returned non-const pointer even when a const array was passed as an argument.
Make two overloads, the way it is done in the C++ standard library:
char* my_strchr( char *place_to_find, char what_to_find)
const char* my_strchr(const char *place_to_find, char what_to_find)
Even though in your case only the second overload would be sufficient (demo) you would not be able to support an important use case, when you need to find a character and then replace it:
// This would not work with only one overload:
char *ptr = my_strchr(vocals2,'e');
if (ptr) {
*ptr = 'E';
}
That is why the non-const overload is necessary.
Note: I assume that you are doing this as a learning exercise, because C-style string functions are no longer necessary for new development, having been replaced with std::string functionality.
Short answer: make the type of the place_to_find const char*
The reason for your error is that you cannot implicitly convert a pointer to a const char to a pointer to a non-const char. If you could, then you could change the char that the pointer points to and it would defeat the purpose of having it a const char type in the first place.
You can implicitly convert a pointer to a non-const char to a pointer to a const char because it does not remove any restrictions.
L.E.: Also, the return value should be a const char*, because again, if you don't, it would remove the const restriction which is not allowed. The only problem with that is that you would not be able to modify the array through the pointer returned. If you also want that, then you would have to overload the method on both char and const char.

Passing an argument to a void(*)(void*)

I am wrapping some sqlite3 C code in C++ and am confused about this type of argument void(*)(void*) in this function
int sqlite3_bind_blob(sqlite3_stmt*, int, const void*, int n, void(*)(void*));
So my wrapper looks like
int Query::Blob(int index, const void* blob, int blob_size, void* memory_management){
return sqlite3_bind_blob(stmt, index, blobl, blob_size, memory_management);
}
I should be able to pass the following to the last argument
Some function to free the blob memory
Either SQLITE_STATIC or SQLITE_TRANSIENT defines
The two defines are unsurprisingly defined as
typedef void (*sqlite_3_destructor_type)(void*);
But I really don't understand the void/void syntax. How can I wrap that in my C++ method to accept a function like delete or the defines?
The type void(*)(void*) is a pointer to a non-member function that takes a single argument of type void * and returns void.
So if your memory_management function is declared as:
void memory_management(void *);
Then it matches this definition, and Query::Blob should be defined as:
int Query::Blob(int index, const void* blob, int blob_size, void (*memory_management)(void *)){
return sqlite3_bind_blob(stmt, index, blobl, blob_size, memory_management);
}
This means that you need to provide a call back that takes one argument, a pointer to void and returns nothing. This has to be a free function (not a non-static method of a class)
Indeed, free is such a function. You can use a delete-like as well:
void myfree(void* data)
{
delete static_cast<MyObject*>(data);
}
You loose type-safety, but if this is to free an object passed as void* somewhere else and also used in callback, this is defined behavior.

I cant understand an expression of type casting

I got a program which has following expression but I cannot undersrand the meaning.
unsigned (*getid)(const char*);
Is this declaration of getid ?
I am confused cause i met such expression for the first time and I couldnt come up with the keyword to search.
Thank you very much in advance.
This isn't a type-cast.
unsigned (*getid)(const char*); declares a pointer to a function that takes a const char* and returns an unsigned [int] and calls this getid.
Further reading:
Function Pointers
It is a function pointer - getid. - with a signature demonstrated beow
e.g.
unsigned mygetid(const char *i) { return 0; }
getid = mygetid;
getid is declared to be a pointer to a function which takes a const char* as an argument and returns an unsigned. Without the parentheses, the declaration would be for a function named getid which returns an unsigned * -- i.e. pointer to an unsigned integer.
For more information, see Programs as Data: Function Pointers.
This is the declaration of a pointer to a function that returns an unsigned andtakes a char * as argument.
example:
// a couple of functions with the same prototypes
unsigned id_getter_1 (const char * name)
{
// ...
}
unsigned id_getter_2 (const char * name)
{
// ...
}
// a pointer to one of these functions
unsigned (*getid)(const char*);
// assigning the function to the pointer
if (ID_TYPE == 1)
getid = id_getter_1;
else
getid = id_getter_2;
// calling one of the functions through pointer
getid("xxx");
This is useful when you want a different code to be used depending on the circumstances. You select a variant of the code, and then use the pointer just as it it was a function name.
You might want to use typedef to make the code more readable:
// define a "pointer to getter function" type
typedef unsigned (* IdGetter) (const char * name);
// declare a "pointer to getter function"
IdGetter my_getter;
Is this declaration of getid ?
Yes it is. There is no casting here but this is a declaration of the pointer to a function that takes const char* as argument and returns unsigned [int] and this pointer is called getid. You can always use this site to find out meanings of such declarations.
keyword to search is: pointer to a function, declaration

cannot convert parameter from `const char *` to `char *`

Given this code:
void group::build(int size, std::string *ips){
/*Build the LL after receiving the
member list from bootstrap*/
head = new member("head");
member *temp1,*temp2;
temp1 = new member(ips[0].data()); // error here
// ....
}
member::member(char *ip){
strcpy_s(this->ip_addr,sizeof(ip),ip);
this->next = NULL;
this->previous = NULL;
}
And a pointer to string defined as:
std::string *ips;
I want to initialize the array, ips with strings but when I try to get the char data from any array member I get the error:
cannot convert parameter from const char * to char *
Why?
The function you are calling expects a pointer to a modifiable buffer, char*. You are passing a pointer to a non-modifiable buffer, const char*.
Since your member function does not modify its input you should change its declaration to receive const char*.
member::member(const char *ip)
Change line
member::member(char *ip)
to
member::member(const char *ip)
and, i'm not sure about your usage of strcpy_s
Well, data() returns a const char*, hence the error. You should change member::member to receive a const char*, as you're copying its value anyway.
Also, note that sizeof(ip) is equal to sizeof(char*), which is just a size of a pointer. You should pass the size of the this->ip_addr buffer instead.
Because member::member is defined to take char * as a parameter, and string.data() is giving a const char * as a value (since it is returning a reference to its own internal memory). You could use const_cast or change member::member method signature.
Change this:
member::member(char *ip)
to this
member::member(const char *ip)
That is, you've to change the parameter type of the constructor.
Alternatively, which is also a better solution, simply make the parameter const std::string &:
member::member(const std::string &)
This approach lets use better interfaces provided by std::string class. These interfaces are much more better than C-string interfaces such as strcpy, strlen, strcat etc.
std::string data has this signature
const char* data() const;
You are trying to call the member c'tor with which expects char * so here is your error.
Change this : member::member(char *ip)
To this : member::member(const char *ip)

'Invalid conversion from some_type** to const some_type**'

I've got a function that requires const some_type** as an argument (some_type is a struct, and the function needs a pointer to an array of this type). I declared a local variable of type some_type*, and initialized it. Then I call the function as f(&some_array), and the compiler (gcc) says:
error: invalid conversion from ‘some_type**’ to ‘const some_type**’
What's the problem here? Why can't I convert a variable to const?
See: Why can't I pass a char ** to a function which expects a const char **? from the comp.lang.c FAQ.
You have a few options to get around what jamesdlin outlined in his answer.
You could use an intermediate variable.
some_type const* const_some_array = some_array;
f(&const_some_array);
You could change the parameters of f.
void f(some_type const* const* some_array);
You probably need to specify some more context, for instance is the argument passed data into or out of (or both?) the function?
Try making your variable const as well:
some_type const *some_array = ....;
This reads as "some_array is a pointer to a const some_type". The code can't modify the thing being pointed at. So you have to declare your variable const before passing it to the function.
(Edited...)