0

When receiving data on wire and sending it to upper applications, normally, in C style, we have a struct for example with a void*:

struct SData{
//... len, size, version, msg type, ...
void* payload;
}

Later in the code, after error checking and mallocating, ..., we can do something as:

if(msgType == type1){
    struct SType1* ptr = (struct SType1*) SData->payload;
}

In C++, an attempt to use unique_ptr fails in the following snippet:

struct SData{
// .. len, size, version, msg type, ...
std::unique_ptr<void> payload;
}

But as you know, this will cause:

error: static assertion failed: can't delete pointer to incomplete type

Is there a way to use smart pointers to handle this?

One solution I found is here: Should std::unique_ptr<void> be permitted

Which requires creating a custom deleter:

void HandleDeleter(HANDLE h)
{
    if (h) CloseHandle(h);
}

using

UniHandle = unique_ptr<void, function<void(HANDLE)>>; 

This will require significantly more additional code (compared to the simple unsafe C Style), since for each type of payload there has to be some logic added.

Makketronix
  • 1,389
  • 1
  • 11
  • 31

1 Answers1

1

This will require significantly more additional code (compared to the simple unsafe C Style), since for each type of payload there has to be some logic added.

The additional complexity is only calling the added destructors. You could use a function pointer instead of std::function since no closure state should ever be used.

If you don't want destructors, but only to add RAII to the C idiom, then use a custom deleter which simply does operator delete or std::free.

Potatoswatter
  • 134,909
  • 25
  • 265
  • 421
  • Could you please elaborate more on the "since no closure state should ever be used?" – Makketronix Oct 03 '17 at 20:19
  • @Makketronix `std::function` is a function pointer plus some encapsulated state — variables or stored arguments. Deleters seldom need more than the object being deleted. – Potatoswatter Oct 03 '17 at 20:22