The problem
Option semantics and reseatable reference semantics are orthogonal. C++ does not implement all combinations:
| Reseatable | Not reseatable | |
| Optional | The reference can be changed to something else, including nothing.
C++ : T* or boost::optional<T&> |
The reference cannot be changed, but it may reference nothing.
C++ : T* const or const boost::optional<T&> |
| Not Optional |
The reference can be changed to something else, but not nothing.
C++ : not implemented. |
The reference cannot change, and always references something.
C++ : T& |
A common issue in C family languages is that option semantics are usually intermingled with reseatable reference semantics (be it pointers in C and C++, or typical references in Java and C#).
The solution
C++ provides a simple compile-time way of ensuring that a given referenced object exists: reference types have no option semantics and can therefore be used to guarantee that the manipulated value is fixed. Therefore, it’s possible to propose an optional type based on pointers, which verifies that the manipulated object is never null.
template <typename T> class safe_ptr { T* data; public: explicit safe_ptr(T& i) : data(&i) {} safe_ptr &operator =(T& i) { data = i; } // Default copy and assignment semantics are correct T& operator *() const { return *data; } T* operator->() const { return data; } bool operator == (const safe_ptr& other) const { return data == other.data; } bool operator != (const safe_ptr& other) const { return data != other.data; } };
Example usage:
std::string a = "A", b = "B"; safe_ptr<std::string> p = a; std::cout << *p; // Outputs 'A' p = b; std::cout << *p; // Outputs 'B'
The issues
This solution is not perfect. First, it fails to interact correctly with inheritance, so a safe pointer to a derived class cannot be implicitly converted to a safe pointer to a base class, and the conversion has to be done manually and explicitly using safe_ptr<Base>( *ptr_to_derived ). Second, it also fails to provide iterator semantics, although that would be expected of a mutable pointer type. And third, it relies on the user’s ability not to dereference null pointers to pass them to the class’ constructor.
0 Responses to “Options and References”
Leave a Reply