Using void in functions. Won't recognise - c++

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);

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.

Argument of type “const [structname] *” is incompatible with parameter of type “const [structname] *”

I am trying to include a structure in a library function in C++.
The structure goes like this:
struct NET_IN_OPERATE_FACERECONGNITIONDB{
DWORD dwSize;
EM_OPERATE_FACERECONGNITIONDB_TYPE emOperateType;
FACERECOGNITION_PERSON_INFO stPersonInfo;
char *pBuffer;
int nBufferLen;
}; `
And the function in which it is included goes like this:
BOOL CLIENT_OperateFaceRecognitionDB(
LLONG lLoginID,
const NET_IN_OPERATE_FACERECONGNITIONDB *pstInParam,
NET_OUT_OPERATE_FACERECONGNITIONDB *pstOutParam,
int nWaitTime = 1000,
);
I'm defining the structure to a pointer by writing the following lines:
const struct NET_OUT_OPERATE_FACERECONGNITIONDB{
DWORD dwSize = sizeof(NET_IN_OPERATE_FACERECONGNITIONDB);
EM_OPERATE_FACERECONGNITIONDB_TYPE emOperateType = NET_FACERECONGNITIONDB_ADD;
FACERECOGNITION_PERSON_INFO FACERECOGNITION_PERSON_INFO1;
char *pBuffer = '\0';
int nBufferLen = 10;
} *pstInParam;
but when I call that structure into the function using this line:
CLIENT_OperateFaceRecognitionDB(m_LoginID, pstInParam, pstOutParam, 1000);
I am getting an error saying
Argument of type “const NET_IN_OPERATE_FACERECONGNITIONDB *” is incompatible with parameter of type “const NET_IN_OPERATE_FACERECONGNITIONDB *”
This is very unusual, because both the argument and the parameter are of the same type. What mistake have I done?
This is very unusual, because both the argument and the parameter are of the same type.
They are not of the same type (which the error message tells you, though it is not very helpful in doing so).
What's going on here is that your declaration of pstInParam is in fact defining an anonymous struct, and then introducing a variable that is a pointer to this anonymous struct.
This is more readily seen in a reduced example, which yields a more helpful error on recent GCC versions:
struct some_struct {
int member;
};
bool some_function(const some_struct*) {
return false;
}
int main()
{
const struct some_struct {
int member = 0;
} *param;
some_function(param);
}
prog.cc: In function 'int main()':
prog.cc:15:22: error: cannot convert 'const main()::some_struct*' to 'const some_struct*' for argument '1' to 'bool some_function(const some_struct*)'
some_function(param)
What you (probably, depending on the ownership semantics of CLIENT_OperateFaceRecognitionDB) want to do is either to declare a some_struct and pass its address to the function:
int main()
{
const some_struct param{0};
some_function(&param);
}
...or to allocate it on the free store:
int main()
{
const some_struct* param = new some_struct{0};
some_function(param);
delete param;
}
In the latter case, please consider using smart pointers if possible.

invalid conversion from 'void*' to class(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 );

const array of func pointers befuddles

void process( int boat ) { ; }
const void(*sequence_A[])( int ) = { process, process }; //ERROR
const void(**func_sequence)( int ) = sequence_A;
(*func_sequence++)( 7 );
Why won't this compile? I want const to refer to the array, not the contents of the array.
Error 1 error C2440: 'initializing' : cannot convert from 'void (__cdecl *)(int)' to 'const void (__cdecl *)(int)'
EDIT: So you guys are saying it doesn't exist. Fair enough. Just to be clear, I'm posting this analogy of the functionality I wanted but this is with int instead of function ptrs
//Compiles without error
int number1 = 7;
int number2 = 3;
const int* sequence_B[] = { &number1, &number2 };
const int** numbers = sequence_B;
int check = **numbers++; //value is 7
int chec2 = **numbers++; //value is 3
Okay, let's analyze the meaning of your statement
const void(*sequence_A[])( int ) = { process, process }; //ERROR
The way I remember the parsing of *x[] is that the second argument of main is char* argv[], so, it's an array of pointers. In other words, sequence_A is to be indexed, and then the result is to be dereferenced.
Then, to that you can apply a function call argument parenthesis with an int value, and as a result you should get a …
const void ?
Well that's not entirely meaningful. You can have a pointer to const void, but you can't dereference that pointer: you can't "get at" the const void directly. Yet here is some pointer to a function that produces as its expression value a const void.
To match that you would need
const void process( int boat ) { ; }
and although I haven't tried it, I doubt that any compiler will accept it. [Update: as it turns out, at least g++ accepts it, so it is one solution. But it's a very unconventional function signature. And not at all what you're after!]
In short, remove that const.
On a related note, as mentioned already in a comment you can't have a const raw array, except in the sense of a raw array of const items.
It's a corner case of the language, a problematic type system aberration inherited from C.
Along with the array type decay to pointer, also problematic.
Addendum: example of how to make the array items const:
void process( int boat ) { ; }
int main()
{
void(* const sequence_A[])( int ) = { process, process }; // OK
//sequence_A[0] = process; //ERROR
}

Boost::GIL bits8* to gray8_ptr_t without reinterpret_cast?

Trying to work by the design guidelines for GIL, I use bits__ for my channel data types. I often have external data I'm wrapping into GIL image views. However, even using the bits__ types for data pointers, I have to add in a reinterpret_cast before I can create my image views. Take the following code
int width = 3;
int height = 2;
boost::gil::bits8 data8[] = {0, 1, 100, 200, 50, 51};
boost::gil::bits8* pBits8 = data8;
boost::gil::gray8_ptr_t pGray8 = pBits8;
boost::gil::gray8_view_t v = interleaved_view(width, height, pGray8, width * sizeof(boost::gil::bits8));
Results in the error on line 6 "error C2440: 'initializing' : cannot convert from 'boost::gil::bits8 *' to 'boost::gil::gray8_ptr_t'
1> Types pointed to are unrelated; conversion requires reinterpret_cast, C-style cast or function-style cast"
Delving into the source code as much as I can, it appears these types really are unreleated. bits8 is just unsigned char, but gray8_ptr_t is a pointer to a struct pixel<bits8,gray_layout_t>. The only element of this struct is a single bits8, so a reinterpret_cast looks safe. It also works fine for the tests I've thrown at it.
However, I wrap external data into image views quite often, and having a reinterpret_cast in every place feels problematic. Is there a safer way of constructing a pixel pointer for use in GIL?
Current workaround:
template<class Dest, class Src>
Dest gil_safe_ptr_cast(Src src)
{
// this cast is unsafe, use reinterpret_cast
BOOST_STATIC_ASSERT(false);
}
template<> boost::gil::gray8_ptr_t gil_safe_ptr_cast(boost::gil::bits8* pBits8)
{
return reinterpret_cast<boost::gil::gray8_ptr_t>(pBits8);
}
boost::gil::bits8* pBits8 = data8;
boost::gil::gray8_ptr_t pGray8 = gil_safe_ptr_cast<boost::gil::gray8_ptr_t>(pBits8); // works
boost::gil::bits16* pBits16 = NULL;
boost::gil::gray8_ptr_t pGray82 = gil_safe_ptr_cast<boost::gil::gray8_ptr_t>(pBits16); // compile error as expected
To convert from bits8* to gray8_ptr_t, create a struct pixel and provide the bits8 to the constructor:
gray8_ptr_t convert_gray8_ptr_t(bits8* src) {
return new struct pixel<bits8,gray_layout_t>(*src);
}
To convert back, use the struct's conversion operator:
bits8* convert_bits8(gray8_ptr_t src) {
bits8* result = new bits8;
*result = (bits8) *src;
return result;
}
Of course both of these functions allocate memory and are probably unnecessary as functions (better as inline code).
template<class Dest, class Src>
Dest gil_safe_ptr_cast(Src src)
{
// this cast is unsafe, use reinterpret_cast
BOOST_STATIC_ASSERT(false);
}
template<> boost::gil::gray8_ptr_t gil_safe_ptr_cast(boost::gil::bits8* pBits8)
{
return reinterpret_cast<boost::gil::gray8_ptr_t>(pBits8);
}
boost::gil::bits8* pBits8 = data8;
boost::gil::gray8_ptr_t pGray8 = gil_safe_ptr_cast<boost::gil::gray8_ptr_t>(pBits8); // works
boost::gil::bits16* pBits16 = NULL;
boost::gil::gray8_ptr_t pGray82 = gil_safe_ptr_cast<boost::gil::gray8_ptr_t>(pBits16); // compile error as expected