Options and References

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&>
Objective Caml : ‘a option ref

The reference cannot be changed, but it may reference nothing.

C++ : T* const or const boost::optional<T&>
Objective Caml : ‘a option

Not Optional
The reference can be changed to something else, but not nothing.

C++ : not implemented.
Objective Caml : ‘a ref

The reference cannot change, and always references something.

C++ : T&
Objective Caml : ‘a

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”


  1. No Comments

Leave a Reply