Home > OS >  Why can you cast a integer as a void pointer but can't with CString?
Why can you cast a integer as a void pointer but can't with CString?

Time:11-30

Just a heads up, I'm referencing from a working code, and I'm trying to implement the same method but with a CString.

The below method that works, casting an integer as a void pointer:

void **pParam = new void*[2];
pParam[0] = reinterpret_cast<void*>(this);
pParam[1] = reinterpret_cast<void*>(iTrayNumber);
_beginthreadex(NULL, 0, &CInspectionDone::InspectionDoneThread, reinterpret_cast<void*>(pParam), 0, NULL);

Whereas if I do the same for CString, I'm getting these errors:

CString strTest = _T("Hello");
void **pParam = new void*[2];
pParam[0] = reinterpret_cast<void*>(this);
pParam[1] = reinterpret_cast<void*>(strTest);

errors:

1>d:\v4\apps\serialcomm.cpp(160) : error C2440: 'reinterpret_cast' : cannot convert from 'CString' to 'void *'
1>        Conversion requires a constructor or user-defined-conversion operator, which can't be used by const_cast or reinterpret_cast

Is it because fundamentally you can't do the same for a CString? I tried searching around the internet and it says the function for reinterpret cast is to convert pointer of one data type to another. Unless maybe pointers are just integers and it's being accepted to be casted..

If there are any explanations on this, I'll greatly appreciate it! Thanks in advance.

CodePudding user response:

reinterpret_cast performs a number of specific casts, all of which are needed only in rather special circumstances. You shouldn't need reinterpret_cast for what you are doing here.

One of the casts allowed with reinterpret_cast is casting one object pointer type to another object pointer type. The effect of this depends on the exact types. This is mostly useful when casting to char* or unsigned char* to obtain the object representation of an object.

reinterpret_cast<void*> is pointless because conversion from any (non-const/volatile) object pointer type to void* is implicit. The cast is not required at all. Even if it is required static_cast will do the same and be less risky (since most use of reinterpret_cast is likely to end with undefined behavior). This conversion doesn't change the pointer value. The void* will point to the same object as the original pointer did. You then need to later cast the void* back to the original type with a static_cast (no reinterpret_cast required either). Casting to other types will almost always end with undefined behavior.

Another conversion reinterpret_cast can perform is between object type pointers and integers. This will map the address of the pointer in some implementation-defined way to an integer value (and back). Again the only way this is useful is if you cast the integer value obtained from a pointer back to its original type. Casting a random integer value to a pointer will not likely result in a pointer value that is usable either. All of this is implementation-defined (except for the round-trip pointer->integer->pointer cast leaving the value unchanged).

However there simply is no specific conversion in the list of possible conversions for reinterpret_cast that allows casting a class type to a pointer type. So CString can't be cast to void* in this way. But there wouldn't be any meaningful way to do such a conversion anyway. What would you expect the resulting pointer value to represent?

You should not need any reintepret_cast here. A simple structure holding the properly-typed types will do:

struct Params {
    CInspectionDone* a;
    int b;
};

void *pParam = new Parames{this, iTrayNumber};

_beginthreadex(NULL, 0, &CInspectionDone::InspectionDoneThread, pParam, 0, NULL);

And then InspectionDoneThread can access the parameters with e.g. static_cast<Params>(arg)->a and delete the parameters with delete static_cast<Params>(arg);.

Or even better use modern C . Since a decade ago there is std::thread, which doesn't require any pointers at all. InspectionDoneThread can just be a non-static member function with the integer as argument with appropriate type instead of needing to be a static member function with void* parameter. And then:

auto mythread = std::thread(&CInspectionDone::InspectionDoneThread, this, iTrayNumber);

or with a lambda:

auto mythread = std::thread([&]{ InspectionDoneThread(iTrayNumber); });
  • Related