invalid conversion from 'void*' to class(c++) - c++

Ok, so here's my code:
StatusType System::AddJobSearcher(void *DS, int engineerID, int reqSalary) {
if(DS == NULL || engineerID < 0 || reqSalary < 0) return INVALID_INPUT;
System* system = DS;
Engineer* engineer = new Engineer(engineerID, reqSalary);
if(!engineer) return ALLOCATION_ERROR;
if(system->All.isIn(*engineer->generateIdKey())) {
delete(engineer);
return FAILURE;
}
system->All.insert(*engineer->generateIdKey(), *engineer);
return SUCCESS;
}
Now, system is a class and DS is supposed to be pointer to one.
When I try to point newly created system to DS(System* system = DS;) I get:
invalid conversion from 'void*' to 'System*' [-fpermissive]
How can I solve that

Since you know DS will be of type System*, you should change the argument type:
StatusType System::AddJobSearcher(System* DS, int engineerID, int reqSalary) {
// ^^^^^^
And if you happen to pass a void* as first argument, you should refactor your code so that you don't have to.

In C++ (opposite to C) you may not implicitly convert a pointer of type void * to a pointer of other type. You have to do this explicitly
System* system = static_cast<System*>( DS );

Related

How do I cast int** to void**?

With the following snippet:
int n = 11;
int* c = &n;
void** v = &c;
I receive the following error in visual studio:
the value of type int** cannot be used to initialize an entity of type void **.
This works fine:
int n = 11;
int* c = &n;
void* v = c;
But this code snippet is for a larger problem in someone's library.
What am I doing wrong with casting a variable to void**?
Complete Example
Using the caen digitizer library the way they try to collect data from the peripheral device has this prototype:
/******************************************************************************
* X742_DecodeEvent(char *evtPtr, void **Evt)
* Decodes a specified event stored in the acquisition buffer writing data in Evt memory
* Once used the Evt memory MUST be deallocated by the caller!
*
* [IN] EventPtr : pointer to the requested event in the acquisition buffer (MUST BE NULL)
* [OUT] Evt : event structure with the requested event data
* : return 0 = Success;
******************************************************************************/
int32_t X742_DecodeEvent(char *evtPtr, void **Evt);
And this is the implementation:
int32_t X742_DecodeEvent(char *evtPtr, void **Evt) {
CAEN_DGTZ_X742_EVENT_t *Event;
uint32_t *buffer;
char chanMask;
uint32_t j,g,size;
uint32_t *pbuffer;
uint32_t eventSize;
int evtSize,h;
evtSize = *(long *)evtPtr & 0x0FFFFFFF;
chanMask = *(long *)(evtPtr+4) & 0x0000000F;
evtPtr += EVENT_HEADER_SIZE;
buffer = (uint32_t *) evtPtr;
pbuffer = (uint32_t *) evtPtr;
eventSize = (evtSize * 4) - EVENT_HEADER_SIZE;
if (eventSize == 0) return -1;
Event = (CAEN_DGTZ_X742_EVENT_t *) malloc(sizeof(CAEN_DGTZ_X742_EVENT_t));
if (Event == NULL) return -1;
memset( Event, 0, sizeof(CAEN_DGTZ_X742_EVENT_t));
for (g=0; g<X742_MAX_GROUPS; g++) {
if ((chanMask >> g) & 0x1) {
for (j=0; j<MAX_X742_CHANNEL_SIZE; j++) {
Event->DataGroup[g].DataChannel[j]= malloc(X742_FIXED_SIZE * sizeof (float));
if (Event->DataGroup[g].DataChannel[j] == NULL) {
for (h=j-1;h>-1;h++) free(Event->DataGroup[g].DataChannel[h]);
return -1;
}
}
size=V1742UnpackEventGroup(g,pbuffer,&(Event->DataGroup[g]));
pbuffer+=size;
Event->GrPresent[g] = 1;
}
else {
Event->GrPresent[g] = 0;
for (j=0; j<MAX_X742_CHANNEL_SIZE; j++) {
Event->DataGroup[g].DataChannel[j] = NULL;
}
}
}
*Evt = Event;
return 0;
}
I use this by:
CAEN_DGTZ_X742_EVENT_t* Evt = NULL; // Creating my event pointer
//Doing some config of the device
X742_DecodeEvent(evtptr, &Evt); //Decode the event data for me to read (Throws error)
Hope this gives some context.
void** means a pointer to a void* object. But there is no void* object in that code to point at! void** does NOT mean "a pointer to any kind of pointer", so please avoid using it as such. If you have a pointer to something which might be an int*, might be a double*, or etc., void* is a better type than void**. Even better would be a template or std::variant or std::any.
But if you have to use a library that is using void** to mean "a pointer to a pointer to a type unknown at compile time" or something like that, you might need to create a void* pointer to work with, or might need to add in casts to get around the fact that the compiler doesn't like this conversion (for good reason). The problem is, there are at least two reasonable ways to do this! (They will end up doing exactly the same thing on many common computer architectures, but this is not guaranteed.)
// LibraryFunc1 takes a void** argument that somehow means an int* pointer.
// But which call is correct?
int* data_in = generate_data();
LibraryFunc1(reinterpret_cast<void**>(&data_in)); // ?
void* p1 = data_in;
LibraryFunc1(&p1); // ?
// LibraryFunc2 returns a void** argument that somehow means an int* pointer.
void** p2 = LibraryFunc2();
int* data_out_1 = static_cast<int*>(*p2); // ?
int* data_out_2 = *reinterpret_cast<int**>(p2); // ?
Based on the function definition shown, the safe usage is unfortunately:
void* tmpEvt;
X742_DecodeEvent(evtptr, &tmpEvt);
auto* Evt = static_cast<CAEN_DGTZ_X742_EVENT_t*>(tmpEvt);
since the library function assumes at *Evt = Event; that *Evt is actually a void* object it can modify. It may usually work to do the simpler thing instead:
CAEN_DGTZ_X742_EVENT_t* Evt = NULL;
X742_DecodeEvent(evtptr, reinterpret_cast<void**>(&Evt));
but this is undefined behavior by the C++ Standard, and might do the wrong thing on some architectures.
You could make the correct way easier by wrapping it in a function:
inline CAEN_DGTZ_X742_EVENT_t* Get_X742_DecodeEvent(char* evtPtr)
{
void* tmpEvt;
X742_DecodeEvent(evtPtr, &tmpEvt);
return static_cast<CAEN_DGTZ_X742_EVENT_t*>(tmpEvt);
}
What am I doing wrong with casting a variable to void**?
There is no meaningful way to convert int** to void**, so what you're trying to do is wrong.
What you may do is
int n = 11;
void* c = &n;
void** v = &c;
But without a complete example, it is not possible to say whether applies to your problem.
That's simply how the language works.
void * pointers get special treatment: a pointer to an arbitrary type can be converted to a pointer to void (as long as doing so doesn't remove cv-qualifiers from the pointer).
void ** gets none of that special treatment. It's just a regular pointer type, like int **.
int32_t X742_DecodeEvent(char *evtPtr, void **Evt)
Since you want to pass CAEN_DGTZ_X742_EVENT_t ** to your function, you should change the parameter type accordingly: CAEN_DGTZ_X742_EVENT_t **Evt.
In comments you were suggested to use void ** v = (void**)&c;.
While you could probably make it work in practice, strictly speaking any access to *v would violate strict aliasing and cause undefined behavior. I wouldn't use that solution.

error: ANSI C++ forbids implicit conversion from `void *' in assignment

I get this error message, and I don't seem to understand it.
What does it mean by ANSI C++ forbids implicit conversion from `void *' in assignment? . And the Fork function only takes the function name and a number
Thread::Fork(VoidFunctionPtr func, int arg)
Error message:
../threads/threadtest.cc: In function `void ServerThread(int)':
../threads/threadtest.cc:72: ANSI C++ forbids implicit conversion from `void *' in assignment
../threads/threadtest.cc:78: implicit declaration of function `int WorkerThread(...)'
REGION:
72 - 78:
nextReq = list -> Remove();
//check till the end
while (nextReq != NULL)
{
WorkerThread(&nextReq);
code:
#include "copyright.h"
#include "system.h"
#include <stdio.h>
#include "request.h"
extern void serve(char *url);
//GLOBAL VARIABLE LIST
List *list;
//----------------------------------------------------------------------
// ThreadTest
// read file and serve urls
//----------------------------------------------------------------------
void
ClientThread(int request)
{
const int sz = 50;
char url[sz];
FILE *fp = fopen("url.txt", "r");
if (!fp)
printf(" Cannot open file url.txt!\n");
else {
int pos = 0;
char c = getc(fp);
while (c != EOF || pos == sz - 1) {
if (c == '\n') {
url[pos] = '\0';
serve(url);
pos = 0;
//Store necessary information in a Request object for each request.
Request req(url, request, 1);
Request *reqq = &req; //req points to the object
list->Append(reqq);
}
else {
url[pos++] = c;
}
c = getc(fp);
}
fclose(fp);
}
}
//----------------------------------------------------------------------
void
ServerThread(int which)
{
Request *nextReq;
//gets the first node off the list
nextReq = list -> Remove();
//check till the end
while (nextReq != NULL)
{
WorkerThread(nextReq);
}
}
//----------------------------------------------------------------------
void
WorkerThread (Request req)
{
serve(req.url);
currentThread -> Yield();
}
//----------------------------------------------------------------------
void
ThreadTest()
{
DEBUG('t', "Entering SimpleTest");
printf("THREAD TEST");
//Thread *c = new Thread("client thread");
Thread *s = new Thread("server thread");
s->Fork(ServerThread, 1);
ClientThread(0);
}
This appears to be one of the offending lines:
nextReq = list -> Remove();
It appears that list->Remove() returns a void *. C++ requires a cast to turn this into another pointer (C does not). So change this to:
nextReq = static_cast<Request *>(list -> Remove());
(Alternatively, consider making List a template class so you can avoid these kinds of unsafe casts. Based on your code, the STL class std::queue<Request> should fulfill your needs here.)
The second offending line is your call to WorkerThread() before it is defined. You need to add a prototype for the function prior to your definition of ServerThread(). Otherwise the compiler does not know what its prototype is, and it should complain once it reaches the real definition of ServerThread() that it does not match the prototype that it deduced earlier.
void WorkerThread(Request);
void
ServerThread(int which)
{
// ...
(Or, since WorkerThread() does not call ServerThread(), you could just swap the order of the definitions of the two functions to resolve the problem.)
Further, note that this code is bad:
Request req(url, request, 1);
Request *reqq = &req; //req points to the object
list->Append(reqq);
You construct an object and then push a pointer to the stack-allocated object onto a list. When ClientThread() returns, this object will be destroyed and you are left with a pointer to an object that no longer exists. Using this pointer will trigger undefined behavior. Consider instead allocating a new Request on the heap by using Request *reqq = new Request(url, request, 1); (but don't forget to delete the object after you process it).
Or, better yet, use std::queue<Request> as I suggested earlier -- then you can just queue.emplace(url, request, 1);. But note that you do need a way to synchronize access to the queue from multiple threads.

Implicit conversion and string::operator=()

I have a problem with implicit conversion.
I have class ConfigValue and it contains two types of values - int and string. Yes, I need to store these two types, because config file contains some int an some string values.
This class has implemented two conversion operators:
ConfigValue::operator int() const {
if( m_type != TYPE_INT )
throw ConfigException( ConfigException::ERR_INVALID_TYPE, m_key );
return m_ival;
}
ConfigValue::operator std::string() const {
if( m_type != TYPE_STRING )
throw ConfigException( ConfigException::ERR_INVALID_TYPE, m_key );
return m_sval;
}
The next class is Config and it has map of values:<std::string, ConfigValue>. Sometimes I need to get some value, so it has implemented method get:
const ConfigValue & Config::get( const std::string& key) const {
auto pos = m_values.find( key );
if( pos == m_values.end() )
throw ConfigException( ConfigException::ERR_MISSING_KEY, key );
return m_values.at(key);
}
And my question and problem goes here:
// error: error: ambiguous overload for ‘operator=’ in ‘msg =
// in one of candidates:
// no known conversion for argument 1 from ‘const ConfigValue’ to ‘const char*’
string msg;
msg = config->get("DEFAULT_MSG");
// ok:
int port;
port = config->get("DEFAULT_PORT");
// ok:
string msg;
msg = static_cast<string>( config->get("DEFAULT_MSG") );
// ok:
string msg;
string tmp = config->get("DEFAULT_MSG");
msg = tmp;
So if I try to assign the value from get() to already created string object, it fails.
I tried to implement operator char*() but I got the same error and "no known conversion .." disappears.
Do I have to implement another conversion operator or something else to use it without static_cast?
Thanks :)
Isn't the need for those implicit conversions because of over-engineering with ConfigValue? It seems to be constructed without need for it. Without it you can get what you need directly from config and all seems more clear and type-safe:
string msg;
msg = config->getString("DEFAULT_MSG");
int port;
port = config->getInt("DEFAULT_PORT");
Try changing
ConfigValue::operator std::string() const
to
ConfigValue::operator const std::string&() const
If that doesn't solve your problem, you might be stuck adding explicit getters for the int and string types

Callback functions with different arguments

I have two functions with a little different functionality, so I can't make them as template functions.
int func64(__int64 a) {
return (int) a/2;
}
int func32(int a) {
return a--;
}
Depending on variable b64, I would like to call func64 or func32. I don't want check if b64 is true many times in my code, so I use pointers to functions.
void do_func(bool b64) {
typedef int (*pfunc32)(int);
typedef int (*pfunc64)(__int64);
pfunc32 call_func;
if (b64)
call_func = func64; //error C2440: '=' : cannot convert from 'int (__cdecl *)(__int64)' to 'pfunc32'
else
call_func = func32;
//...
call_func(6);
}
How can I avoid this error and cast call_func to pfunc32 or pfunc64?
The language requires all functions called through the same function pointer to have the same prototype.
Depending on what you want to achieve, you could use the pointer/cast aproach already mentioned (which satisfies this requirement at the loss of type safety) or pass a union instead:
union u32_64
{
__int64 i64;
int i32;
};
int func64(union u32_64 a) {
return (int) a.i64/2;
}
int func32(union u32_64 a) {
return --a.i32;
}
void do_func(bool b64) {
typedef int (*pfunc)(union u32_64);
pfunc call_func;
if (b64)
call_func = func64;
else
call_func = func32;
//...
union u32_64 u = { .i64 = 6 };
call_func(u);
}
Pass a void pointer and cast it in the function body.
Of course this means less compiler control if you use the wrong type; if you call func64 and pass an int to it the program will compile and produce wrong results without giving you any tip of what is going wrong.
int func64(void *a) {
__int64 b = *((__int64*) a);
return (int) b/2;
}
int func32(void *a) {
int b = *((int *) a)
return b-1;
}
I need to call func32() or func64() depending on flag b64
So do that:
void do_func(bool b64) {
if (b64)
func64(6);
else
func32(6);
}
Well, first of all, please note that function func32 is returning the input argument as is.
This is because with return a--, you are returning the value of a before decrementing it.
Perhaps you meant to return a-1 instead?
In any case, you can simply declare this function as int func32(__int64 a).
This way, it will have the same prototype as function func64, but will work exactly as before.
BTW, calling a function through a pointer might be more "expensive" than a simple branch operation, so depending on your application, you might be better off with a simple if/else conditional statement...
Make a wrapper for func64:
int func64_as_32(int a) {
return func64(a);
}
Now you can assign either func32 or func64_as_32 to call_func since they have the same signature. The value you pass in, 6, has type int so passing it to func64_as_32 has the same effect as passing it directly to func64.
If you have call sites where you pass in a value of type __int64 then you'd do it the other way around, wrap func32.
As bool in C++ converts to int ( true => 1, false => 0 ) you can use b64 as array index. So take SJuan76's advice, convert your functions prototype to int f(void*) and put them into array int (*array_fun[2])(void* x); . You can call these functions then like that :
int p = 6;
array_fun[b64](&p);

Using void in functions. Won't recognise

I'm having a problem with this function. The function is supposed to return a type of StoredData.
This is my struct:
struct StoredData
{
void* data;
int size;
int type;
int compareValue;
StoredData():
size(0),
type(0),
compareValue(0){}
};
And this is my function:
StoredData SDI::Array::create(int size, int type, int compareValue)
{
StoredData temp;
void* data;
int input;
int input2;
std::cout<<"What type of data would you like to insert?"<<std::endl;
std::cout<<"1 - Integer"<<std::endl;
std::cout<<"2 - Boolean"<<std::endl;
std::cin>>input;
std::cout<<"What is the value?"<<std::endl;
std::cin>>input2;
switch (input)
{
case 1:
size = sizeof(int);
type = 0;
data = new int;
*data = (int)input2;
break;
case 2:
size = sizeof(bool);
type = 1;
data = new bool;
*data = (bool)input2;
break;
}
temp.compareValue=input2;
temp.data = data;
temp.type = type;
temp.size = size;
}
Unfortunately, I'm having a problem with the line within the case statements with
*data = (bool)input2;
The error that I'm getting is that it must be a pointer to a complete object type. I need the void variable to recognize the data, and I'm getting no luck. Anybody know a workaround?
I'm getting 2 error messages for each. The first is,
illegal indirection
And the second ones are,
error C2440: '=' : cannot convert from 'int' to 'void *'
error C2440: '=' : cannot convert from 'bool' to 'void *'
You can't dereference a void pointer. You will have to cast it to a pointer type you can dereference:
*(bool *) data = (bool) input2;
You are attempting to dereference a void pointer and set its value:
*data = (bool)input2;
This is meaningless to the compiler. What type will the result of *data be?
You need to cast the void* to something meaningful first:
*(bool*)data = (bool)input2;
Alternatively, you could initialize your dynamic variables with the correct values when you create them:
data = new int(input2);
...
data = new bool(input2);
Which wouldn't require you to cast anything.
void is an incomplete type.You may not create objects of incomplete type.
You can't dereference a plain void*, as it could point to basically anything. You aither have to make it point to something other (assigning to another pointer):
bool* bool_pointer = new bool;
*bool_pointer = static_cast<bool>(input2);
data = bool_pointer;
Or use typecasting:
*reinterpret_cast<bool*>(data) = static_cast<bool>(input2);