Sign in to follow this  

[C++] Ownership protection

This topic is 3632 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Consider the following code, in C++:
void foo(std::auto_ptr<int>);

void bar() 
{
  std::auto_ptr<int> p(new int());
  foo(p);
  foo(p);
}
There is no way of making the second call to foo(p) generate a compiler error (though it's certainly possible to generate a runtime error through a slight modification of the auto_ptr constructor). Assuming that we can implement a new version of auto_ptr with different semantics but the same philosophy of "I own this pointer", how much would one have to change the above piece of source so that the second call generates an error but the first doesn't?

Share this post


Link to post
Share on other sites
It won't generate a compile error, but foo can certainly assert the pointer to be valid, which would raise an error on the second call.

Personally, I never use auto_ptr. Mutating copy constructors are bad mojo. boost::scoped_ptr removes this weirdness. s/std::auto_ptr/boost::shared_ptr/g would cause both function calls to result in a compile error (no copy constructor), leading the programmer to change the argument to a boost::shared_ptr<int> const&, which works just dandy.

Share this post


Link to post
Share on other sites
On the face of it, it doesn't seem possible without some truly evil macro hackery. To generate a compiler error, you'd basically need the call to foo() to actually change the type of p; which isn't allowed in C++'s static type system.

Share this post


Link to post
Share on other sites
Quote:
Original post by Sneftel
It won't generate a compile error, but foo can certainly assert the pointer to be valid, which would raise an error on the second call.


Indeed. The issue mostly appears when one wishes to implement an auto_ptr-like object which cannot be null. Thus leading to the existence of a 'given away' state where the object cannot undergo any transformation except for being destructed. The point of this question would be to detect at compile time usage of 'given away' pointers.

Quote:
s/std::auto_ptr/boost::shared_ptr/g would cause both function calls to result in a compile error (no copy constructor), leading the programmer to change the argument to a boost::shared_ptr<int> const&, which works just dandy.


I agree. However, please assume (as the original example does) that foo requires exclusive ownership.

Share this post


Link to post
Share on other sites
Not possible. Type analysis is static. One line within a variable context is treated like any other.


void foo(std::auto_ptr<int>);

void bar()
{
std::auto_ptr<int> p(new int());
if(someProgram.halts())
{
foo(p);
}
foo(p);
}

Share this post


Link to post
Share on other sites
Quote:
Original post by Sneftel
if(someProgram.halts())


You know you're a computer scientist, when...

Thank you for your arguments, both of you. That's pretty convincing.

Share this post


Link to post
Share on other sites
You'd need linear types, which C++ definitely doesn't have.

Vault is a C-like research language with a linear type system that can do this sort of thing (ensure you never write to a closed file, etc).

Share this post


Link to post
Share on other sites
I was testing something like this for serialization:
template < int Size >
struct CheckSize
{
enum { SIZE = (Size >= 0 ? Size : -1) };
};

template < int BufSize >
struct Serializer
{

template < class T >
Serializer< CheckSize< BufSize - sizeof(T) >::SIZE > write( T )
{
return Serializer< CheckSize< BufSize - sizeof(T) >::SIZE >();
}
};

template <>
struct Serializer<-1>
{
private:
Serializer() {};
};


int main()
{
// fails while writing 200
Serializer<10>().write( 17 ).write( 20 ).write(200);
}



I believe that chaining calls would be the only way to do this, you'd probably need to wrap call to foo in a function pointer, then call it in a chain.

Quote:
Assuming that we can implement a new version of auto_ptr with different semantics but the same philosophy of "I own this pointer", how much would one have to change the above piece of source so that the second call generates an error but the first doesn't?


I believe this could work:
safe_ptr<int>(new int()).call(foo)
// .call(???) no longer exists in second specialization

Share this post


Link to post
Share on other sites
Antheus: I still don't think that will work.

For example:

// this would give a type error:
// safe_ptr<int>(new int()).call(foo).call(foo)

// but this is type correct:

safe_ptr<int> p(new int());
p.call(foo);
p.call(foo);


I think there is a way though, but I'll have to think about it. You need to make it impossible to access the raw safe_ptr, and dress it in a higher-level wrapper based on Antheus's .call idea (the resulting interface might be quite awkward to use in practice).

Share this post


Link to post
Share on other sites

This topic is 3632 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

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