Passing a std::unique_ptr as a parameter to a function - c++

I got a structure and a function like the following:
struct MYOVERLAPPED : public OVERLAPPED
{
//...
};
void func1(std::unique_ptr<MYOVERLAPPED> pBuf)
{
//...
};
I am obtaining a pointer to MYOVERLAPPED which i want to pass to the func1-function.
The problem i encounter is, that no matter what i try i get the following errors :
What i did try already are the following:
Try1:
std::unique_ptr<OVERLAPPED> pOver(//....)
HandleAcceptIndication(std::move(pOver));
Error: Error 1 error C2440: 'initializing' : cannot convert from
'_OVERLAPPED **' to 'MYOVERLAPPED *'
Try2:
HandleAcceptIndication(new ACCEPT_OVERLAPPED);
Error 1 error C2664: 'HandleAcceptIndication' : cannot convert
parameter 1 from 'MYOVERLAPPED *' to 'std::unique_ptr<_Ty>'
Anyone knows how i can pass this casted pointer of OVERLAPPED to MYOVERLAPPED to the function and why Try2 does not work either since i casually use std::unique_ptr<MYOVERLAPPED> pO(new MYOVERLAPPED) which does work...?

While you cannot convert from std::unique_ptr<base> to std::unique_ptr<derived> directly, it is not too hard to write a cast function that will be safe (i.e. not leak the resource under any circumstance, and only succeed if the cast is valid:
template <typename Dst, typename Src>
std::unique_ptr<Dst> unique_dynamic_cast( std::unique_ptr<Src>& ptr ) {
Src * p = ptr.release(); // [1]
std::unique_ptr<Dst> r( dynamic_cast<Dst*>(p) ); // [2]
if ( !r ) {
ptr.reset( p ); // [3]
}
return r; // [4]
}
The basic idea is that we need to extract the pointer from the std::unique_ptr and set it aside in [1]. We cannot try dynamic_cast directly, as if that fails, ptr would have released ownership, and the memory would be leaked. Then we try and perform the dynamic_cast [2] from the local pointer to the requested type of pointer and pass ownership onto the r result unique pointer. If the dynamic_cast fails, then r will be null, and we need to return ownership of the memory to the original std::unique_ptr [3], for calling code to decide what to do with it. We then return the converted std::unique_ptr to the caller in [4].

This doesn't work because you're trying to cast the wrong way in the inheritance hierarchy. You're trying to convert from Base* to Derived* implicitly.

unique_ptr<A> and unique_ptr<B> are unrelated types. You can't convert between them unless an implicit conversion exists between A* and B* (thanks UncleBens), which is not true in this case. Also you should not cast down the inheritance hierarchy with an instance that is not the subclass you are casting to. In this case, you're trying to cast a OVERLAPPED to a MYOVERLAPPED which is an invalid cast because an OVERLAPPED is not a MYOVERLAPPED. That's why you can't convert between the unique_ptr types in the first place.
If you are just trying to pass a unique_ptr to func1, you can do it like this:
func1(shared_ptr<MYOVERLAPPED>(new MYOVERLAPPED));
Also, by passing a unique_ptr to a function, the pointer in the original one gets set to NULL. Consider using references or shared_ptrs if you are not creating the unique_ptr as a temporary and passing it to the function and you need to use the same instance later.

Related

Release and cast data of a unique_ptr to another without copying

I have a unique_ptr of an array of floats that I would like to change to a unique_ptr of an array of uint8_t in my function. In other words, unique_ptr<float[]> --> unique_ptr<uint8_t[]>.
This is what I have tried
void my_function(std::unique_ptr<float*> data) {
std::unique_ptr<uint8_t*> converted_data(reinterpret_cast<uint8_t*>(data.release()));
// ...
// Processing converted_data ...
}
Since I am getting this error: no matching constructor for initialization of 'std::unique_ptr<uint8_t *>', I was wondering if it is possible to achieve this goal without copying the data.
You are casting to an incompatible type.
data.release() is of type float** since it returns a raw pointer to whatever was in the unique_ptr (float* in this case). You should cast to uint_8t** instead ( though it still looks like a bad idea).

Syntax Error: Call Member Function Pointer using Pointer to Object

I have a tricky syntax error which I cannot figure out. I am trying to run a function delegate where the context is a pointer to an object.
Syntax error:
((object)->*(ptrToMember)) // the compiler doesn't like the ->*
Where object is of the type Component*
And ptrToMember is of the type void (Component::*EventCallback) ()
Below is the code with the syntax error:
typedef void (Component::*EventCallback) ();
...
std::weak_ptr<Component> wc( mySharedPtr );
EventCallback ec = &Component::run;
((wc.lock())->*(ec))(); // syntax error
(wc.lock()->(*ec))(); // simpler version but still syntax error
// This is ok, but is there any significant time or memory involved in this reference object creation?
Component& wcc = *wc.lock();
(wcc.*ec)();
wc.lock() returns a std::shared_ptr<Component> but you are expecting it to return a raw Component* pointer instead. You cannot call the ->* on the std::shared_ptr itself. You have to ask it for the Component* pointer it is holding, and then you can use the ->* operator on that pointer, eg:
(wc.lock().get()->*ec)();
Since you are dealing with a std::weak_ptr, which could expire before you use it, you should make sure the Component object is actually available after locking before you try to access it:
if (auto sptr = wc.lock()) {
(sptr.get()->*ec)();
}
else {
// wc had expired
}
The result of wc.lock() is a shared_ptr. This is one of the few cases where the smart pointer diverges from a dumb pointer. shared_ptr does not implement operator ->*, so your first syntax can't work. (It's not a syntax error, you're just trying to do something shared_ptr doesn't support.)
You've found a workaround though.

handling memory for IDL sequence return types

I have an idl definition as follow
typedef sequence<octet> ByteArray;
interface Connection {
ByteArray get_id ();
}
And there is this client side code
ByteArray * idToEncrypt = connection->get_id();
encryptId(idToEncrypt);
... // rest of code
The function encryptId() has the signature ByteArray* encryptId(ByteArray* idToEncrypt). I cannot change this signature.
For automatic memory handling, the type of idToEncrypt was changed to ByteArray_var. The problem is I dont know how to get 'ByteArray *' from ByteArray_var and pass it to encryptId().
Is there a way to automatically handle memory allocated "idToEncrypt" and still pass it to encryptId() as "ByteArray *"?
You should look at the _var C++ mapping in the CORBA specs.
For a sequence type var, I think the best approach might be to use the inout() member, i.e.:
ByteArray_var idToEncrypt = connection->get_id();
encryptId(&idToEncrypt.inout());
inout returns a non-const reference and you're just taking the address of the underlying object with &.
Do note: inout does dereference the internal pointer, so it would be illegal to call inout() on a _var that doesn't hold a pointer. However, the call to get_id() must always return a valid pointer, so the code is OK without checking.
If you need a generic approach where you don't know if the _varis initialized, you could use:
ByteArray* p = idToEncrypt.operator->();
as operator-> seems to be the only way to directly get at the pointer.

Trouble constructing shared_ptr

I'm new to smart pointers, and I'm in the process of hitting every stumbling block.
I have a struct texture_t:
struct texture_t
{
hash32_t hash;
uint32_t width;
uint32_t height;
uint32_t handle;
};
When I try and make a shared_ptr of this struct using this line:
auto texture_shared_ptr = std::make_shared<texture_t>(new texture_t());
I get this error:
error C2664: 'mandala::texture_t::texture_t(const mandala::texture_t &)' : cannot convert parameter 1 from 'mandala::texture_t *' to 'const mandala::texture_t &'
Where is this error coming from and how can I avoid it?
The point of std::make_shared<T>(args...) is to allocate a T object constructed with parameters args.... The idea behind this operation is that std::shared_ptr<T> conceptually maintains two allocated objects:
A pointer to type T.
A record tracking the number of current std::shared_pt<T> and the number of std::weak_ptr<T> objects referring to the object.
When constructing a std::shared_ptr<T> the constructor does a second allocation to construct the record for its internal book keeping. std:make_shared<T>(args...) does just one memory allocation.
The error you saw results from an attempt to construct a mandala::texture_t using a mandala::texture_t* but the only one argument constructor mandala::texture_t has is the copy constructor. However, the pointer doesn't qualify as argument to the copy constructor.
You are not supposed to pass a newed pointer to std::make_shared. You just need to pass arguments from which a texture_t can be constructed to it.

Safely checking the type of a variable

For a system I need to convert a pointer to a long then the long back to the pointer type. As you can guess this is very unsafe. What I wanted to do is use dynamic_cast to do the conversion so if I mixed them I'll get a null pointer. This page says http://publib.boulder.ibm.com/infocenter/lnxpcomp/v7v91/index.jsp?topic=/com.ibm.vacpp7l.doc/language/ref/clrc05keyword_dynamic_cast.htm
The dynamic_cast operator performs
type conversions at run time. The
dynamic_cast operator guarantees the
conversion of a pointer to a base
class to a pointer to a derived class,
or the conversion of an lvalue
referring to a base class to a
reference to a derived class. A
program can thereby use a class
hierarchy safely. This operator and
the typeid operator provide run-time
type information (RTTI) support in
C++.
and I'd like to get an error if it's null so I wrote my own dynamic cast
template<class T, class T2> T mydynamic_cast(T2 p)
{
assert(dynamic_cast<T>(p));
return reinterpret_cast<T>(p);
}
With MSVC I get the error "error C2681: 'long' : invalid expression type for dynamic_cast". It turns out this will only work with classes which have virtual functions... WTF! I know the point of a dynamic cast was for the up/down casting inheritance problem but I also thought it was to solve the type cast problem dynamically. I know I could use reinterpret_cast but that doesn't guarantee the same type of safety.
What should I use to check if my typecast are the same type? I could compare the two typeid but I would have a problem when I want to typecast a derived to its base. So how can I solve this?
dynamic_cast can be used only between classes related through inheritance. For converting a pointer to long or vice-versa, you can use reinterpret_cast. To check whether the pointer is null, you can assert(ptr != 0). However, it is usually not advisable to use reinterpret_cast. Why do you need to convert a pointer to long?
Another option is to use a union:
union U {
int* i_ptr_;
long l;
}
Again, union too is needed only seldom.
I've had to do similar things when loading C++ DLLs in apps written in languages that only support a C interface. Here is a solution that will give you an immediate error if an unexpected object type was passed in. This can make things much easier to diagnose when something goes wrong.
The trick is that every class that you pass out as a handle has to inherit from a common base class.
#include <stdexcept>
#include <typeinfo>
#include <string>
#include <iostream>
using namespace std;
// Any class that needs to be passed out as a handle must inherit from this class.
// Use virtual inheritance if needed in multiple inheritance situations.
class Base
{
public:
virtual ~Base() {} // Ensure a v-table exists for RTTI/dynamic_cast to work
};
class ClassA : public Base
{
};
class ClassB : public Base
{
};
class ClassC
{
public:
virtual ~ClassC() {}
};
// Convert a pointer to a long handle. Always use this function
// to pass handles to outside code. It ensures that T does derive
// from Base, and that things work properly in a multiple inheritance
// situation.
template <typename T>
long pointer_to_handle_cast(T ptr)
{
return reinterpret_cast<long>(static_cast<Base*>(ptr));
}
// Convert a long handle back to a pointer. This makes sure at
// compile time that T does derive from Base. Throws an exception
// if handle is NULL, or a pointer to a non-rtti object, or a pointer
// to a class not convertable to T.
template <typename T>
T safe_handle_cast(long handle)
{
if (handle == NULL)
throw invalid_argument(string("Error casting null pointer to ") + (typeid(T).name()));
Base *base = static_cast<T>(NULL); // Check at compile time that T converts to a Base *
base = reinterpret_cast<Base *>(handle);
T result = NULL;
try
{
result = dynamic_cast<T>(base);
}
catch(__non_rtti_object &)
{
throw invalid_argument(string("Error casting non-rtti object to ") + (typeid(T).name()));
}
if (!result)
throw invalid_argument(string("Error casting pointer to ") + typeid(*base).name() + " to " + (typeid(T).name()));
return result;
}
int main()
{
ClassA *a = new ClassA();
ClassB *b = new ClassB();
ClassC *c = new ClassC();
long d = 0;
long ahandle = pointer_to_handle_cast(a);
long bhandle = pointer_to_handle_cast(b);
// long chandle = pointer_to_handle_cast(c); //Won't compile
long chandle = reinterpret_cast<long>(c);
// long dhandle = pointer_to_handle_cast(&d); Won't compile
long dhandle = reinterpret_cast<long>(&d);
// send handle to library
//...
// get handle back
try
{
a = safe_handle_cast<ClassA *>(ahandle);
//a = safe_handle_cast<ClassA *>(bhandle); // fails at runtime
//a = safe_handle_cast<ClassA *>(chandle); // fails at runtime
//a = safe_handle_cast<ClassA *>(dhandle); // fails at runtime
//a = safe_handle_cast<ClassA *>(NULL); // fails at runtime
//c = safe_handle_cast<ClassC *>(chandle); // Won't compile
}
catch (invalid_argument &ex)
{
cout << ex.what() << endl;
}
return 0;
}
Remember that in Windows 64, a pointer will be a 64-bit quantity but long will still be a 32-bit quantity and your code is broken. At the very least, you need to make the choice of integer type based on the platform. I don't know whether MSVC has support for uintptr_t, the type provided in C99 for holding pointers; that would be the best type to use if it is available.
As for the rest, others have addressed the why's and wherefore's of dynamic_cast vs reinterpret_cast sufficiently.
reinterpret_cast is the correct cast to use here.
This is pretty much the only thing it can do safely.
reinterpret_cast from a pointer type to a type T and back to the original pointer type yields the original pointer. (Assuming T is a pointer or integer type that is at least as big as the original pointer type)
Note that reinterpret_cast from a pointer type to T is unspecified. There are no guarantees about the value of the T type, except that if you then reinterpret_cast it back to the original type, you get the original value. So assuming you don't try to do anything with the intermediate long value in your case, reinterpret_cast is perfectly safe and portable.
Edit: Of course this doesn't help if you don't know at the second cast, what the original type was. In that case,you're screwed. The long can't possibly in any way carry type information about which pointer it was converted from.
You can use reinterpret_cast to cast to an integral type and back to the pointer type. If the integral type is large enough to store the pointer value, then that conversion will not change the pointer value.
As others already say, it is not defined behavior to use dynamic_cast on a non-polymorphic class (except when you do an upcast, which is implicit anyway and be ignored here), and it also only works on pointers or references. Not on integral types.
You better use ::intptr_t found in on various posix systems. You can use that type as your intermediate type you cast to.
Regarding your check whether the conversion will succeed, you can use sizeof:
BOOST_STATIC_ASSERT(sizeof(T1) >= sizeof(T2));
will fail at compile time if the conversion couldn't be done. Or continue to use assert with that condition, and it will assert at run-time instead.
Warning: This won't prevent you from casting T* to intptr_t back to U* with U another type than T. Thus, this only guarantees you the cast won't change the value of the pointer if you cast from T* to intptr_t and back to T*. (Thanks to Nicola pointing out you may expect another protection).
What you want to do sounds like a really bad and dangerous idea, but if you MUST do it (i.e. you're working in a legacy system or on hardware that you know will never change), then I would suggest wrapping the pointer in some kind of simple struct that contains two members: 1) a void pointer to your object instance and a string, enum, or some other kind of unique identifier that will tell you what to cast the original void* to. Here's an example of what I meant (note: I didn't bother testing this so there may be syntactical errors in it):
struct PtrWrapper {
void* m_theRealPointer;
std::string m_type;
};
void YourDangerousMethod( long argument ) {
if ( !argument )
return;
PtrWrapper& pw = *(PtrWrapper*)argument;
assert( !pw.m_type.empty() );
if ( pw.m_type == "ClassA" ) {
ClassA* a = (ClassA*)pw.m_theRealPointer;
a->DoSomething();
} else if (...) { ... }
}
dynamic_cast<> is a cast intended to be used only on convertible types (in the polymorphic sense). Forcing the cast of a pointer to a long (litb correctly suggests the static_assert to ensure the compatibility of the size) all the information about the type of the pointer are lost. There's no way to implement a safe_reinterpret_cast<> to obtain the pointer back: both value and type.
To clarify what I mean:
struct a_kind {};
struct b_kind {};
void function(long ptr)
{}
int
main(int argc, char *argv[])
{
a_kind * ptr1 = new a_kind;
b_kind * ptr2 = new b_kind;
function( (long)ptr1 );
function( (long)ptr2 );
return 0;
}
There's no way for function() to determine the kind of pointer passed and "down" cast it to the proper type, unless either:
the long is wrapped by an object with some information of the type.
the type itself is encoded in the referenced object.
Both the solutions are ugly and should be avoided, since are RTTI surrogates.
also, better use size_t instead of a long -- I think this type is ensured to be compatible with the size of the address space.
As soon as you decided to cast a pointer to a long, you threw type safety to the wind.
dynamic_cast is used to cast up & down a derivation tree. That is, from a base class pointer to a derived class pointer. If you have:
class Base
{
};
class Foo : public Base
{
};
class Bar : public Base
{
};
You can use dynamic_cast in this way...
Base* obj = new Bar;
Bar* bar = dynamic_cast<Bar*>(obj); // this returns a pointer to the derived type because obj actually is a 'Bar' object
assert( bar != 0 );
Foo* foo = dynamic_cast<Foo*>(obj); // this returns NULL because obj isn't a Foo
assert( foo == 0 );
...but you can't use dynamic cast to cast in to an out of a derivation tree. You need reinterpret_cast or C-style casts for that.