Sign in to follow this  
Storyyeller

pointer to temporary

Recommended Posts

Suppose I have a POD struct Foo, a class Bar, which contains the data required to fill a Foo, but can also be in an invalid state. and a function void DoStuffWithFooPtr(Foo* arg) I want to be able to do something like void DoStuffWithBar(const Bar& arg) { DoStuffWithFooPtr( arg.CreateFoo() ); } where the generated pointer is null if arg is invalid, and otherwise points to a stack allocated Foo object constructed from the data in arg. Is this even possible to do? What is the scope of arg? How do I make sure that the pointer is valid when DoStuffWithFooPtr is called, but is all cleaned up automatically afterwards? What code would I put inside Bar::CreateFoo()? By the way, Foo and DoStuffWithFooPtr are part of a library, so I can't really mess with them. DoStuffWithFooPtr doesn't take ownership, and can accept a null pointer.

Share this post


Link to post
Share on other sites
Quote:
Original post by Storyyeller
Is this even possible to do?


Yes, but it's needlessly tricky. Using null pointers to represent 'maybe' objects is a long-standing concept for C and C++ programmers, but it's honestly a hack. You can fix this by using boost::optional.

With your current setup, you need some way to manage the lifetime of the pointed-at Foo, and if CreateFoo() is going to dynamically allocate and return, then you don't have a way to do this. Unless of course you use a smart pointer class instead of a regular pointer; but then you might as well just use boost::optional.

Also, DoStuffWithFooPtr() would have to accept a const Foo*, because you can't pass a reference or pointer to a non-const temporary. (C++ disallows this as a safeguard, although there's no real reason it's necessary for the compiler to do its work. The reasoning is that there is no way for the user to inspect the changes that are made, because there is no way to refer to the temporary afterwards - it's temporary.)

Quote:
What is the scope of arg?


Which one? :)

The scope of the 'const Bar& arg' parameter to DoStuffWithBar(), and the 'const /* !! */ Foo* arg' parameter to DoStuffWIthFooPtr(), in each case is the function itself.

The temporary pointer created by 'arg.CreateFoo()', which is what I assume you actually care about, has a scope that extends just long enough for it to be passed to the function. But that won't clean up the pointed-at Foo.

Quote:
How do I make sure that the pointer is valid when DoStuffWithFooPtr is called, but is all cleaned up automatically afterwards? What code would I put inside Bar::CreateFoo()?


You can't do it that way, sorry.

Quote:
By the way, Foo and DoStuffWithFooPtr are part of a library, so I can't really mess with them. DoStuffWithFooPtr doesn't take ownership, and can accept a null pointer.


... Oh.
You won't be able to use a temporary then, considering the const-correctness thing. The purpose of DoStuffWithBar() is to act as a wrapper, yeah? So what's wrong with:


void DoStuffWithBar(const Bar& arg) // maybe not 'const'?
// A non-member function that returns void and has only const arguments is kind
// of useless; how is calling it going to affect anything else in the program?
{
Foo* API_representation = arg.CreateFoo();
DoStuffWithFooPtr(API_representation);
// if (API_representation != null) { arg.copyFrom(API_representation); }
delete API_representation; // assuming it was new'd
// but you should be using a smart pointer or boost::optional or something
// like that *anyway*, honestly
}


For that matter, you might even make it a member function; that lets you convert the API's procedural interface into a more OO one. ;)

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this