
Mathias Gaunard wrote:
Angel Tsankov wrote:
Is there any interest in a class template which acts like a pointer and guarantees at compile time and at no CPU or memory cost (except when a call to any of its methods is not inlined) that the pointer is not null?
Preventing empty or invalid cases is always good. For example I think it's a shame Boost.Function, Boost.Any and the Boost Smart Pointers don't do it.
As for forcing a pointer to not be empty, I suppose you're talking of making overloads of constructor and operator= for `int' and make them generate errors?
No. In C++, an int cannot be converted implicitly to a pointer, unless the int is the NULL constant, which is not a valid value for unnullable_ptr. Therefore, one should never need to construct unnullable_ptr from an int or to assign an int to an unnullable_ptr so there is no need to have overloads of constructor and operator= for int. Currently, an unnulalble_ptr is constructed directly from the pointee like this: T t; UnnullablePtr<T> pointer_to_t(t); Constructors take the pointee by reference, and apart from the implicit copy assignment there are no other mutable member functions. This is how the unnullability is guaranteed at compile time. On a side note, the behaviour of these constructors is inconsistent with the behaviour of the copy constructor (which creates a copy of the passed unnullable_ptr rather than a pointer to the passed unnullable_ptr). I'll probably fix this by making the 'inconsistent' constructors private, adding a (free) function template that calls the 'incosistent' constructors, and making that function template a friend.
Do you still provide pointer arithmetic and implicit upcasting?
Yes, implicit upcasting as well as the usual casts to void*, and T const* are supported (I've even written several unit tests especially to check the conversions). Implicit conversion from array to unnullable_ptr is also supported. As for pointer arithmetic, I've not yet needed it to work with unnullable_ptr's, so I've not considered implementing it. Nevertheless, it turns out that pointer arithmetic is partially supported (via the convertion operator from unnullable_ptr to C pointer); this is to say that subtracting unnullable_ptr's works, but subtracting int's from (or adding int's to) unnullable_ptr's doesn't yet. In fact, subtracting an int from (as well as adding an int to) an unnullable_ptr might result in a null pointer so the result need to be checked. However, the current implementation of unnullable_ptr is exactly as effective as a built-in C pointer (or at least allows instances of unnulable_ptr to be that effective) and I would like to keep it that way. So, subracting and adding int's will probably not be supported, unless a zero-overhead way is devised to guarantee unnullability of the result from these operations.
I personally stay away from pointers, which I associate with bad programming. boost::ref already provides a safe way to do what you want, and better IMHO. It is not required to use pointers at all with it. And you *can* get the wrapped pointer resource with get or get_pointer.
As I mentioned in my first post, boost::ref does not support the natural syntax for access to the wrapped resource. unnullable_ptr does -- it overloads 'operator ->' and 'operator T*'. (The latter implicitly provides dereferencing, i.e. there is no need to overload 'operator *'.) A known limitation is that unnulalble_ptr cannot be used with member functions (because there is no such thing as a reference to member function from which an unnullable_ptr is to be initialized). In order to be as clear as possible, I could provide all the source code of unnullable_ptr (157 lines) but I'm afraid that this does not meet the Boost posting guidelines. So, I think of uploading the code to the Vault. Angel Tsankov