Xref: utzoo comp.lang.c++:11010 comp.std.c++:518 Path: utzoo!censor!geac!torsqnt!news-server.csri.toronto.edu!cs.utexas.edu!usc!apple!motcsd!mcdcup!mcdhup!mcdchg!tellab5!balr!clrcom!clrcom.clear.com!rmartin From: rmartin@clrcom.clear.com (Bob Martin) Newsgroups: comp.lang.c++,comp.std.c++ Subject: Smart Pointers -- A proposed language extension Message-ID: <1990Dec28.203554.21028@clear.com> Date: 28 Dec 90 20:35:54 GMT Sender: rmartin@clear.com (Bob Martin) Organization: Clear Communications, Inc. Lines: 169 Smart Pointers for C++ A Proposal for A new language feature REQUEST FOR COMMENTS THE PROBLEM The facilities of C++ allow for overloading the pointer operators so as to create "smart pointers". These are classes which behave in some ways as pointers to an object, but have other more intelligent behaviors as well. For example it would be possible to create a smart pointer to a block of bytes which would not allow itself to be assigned any value outside the bounds of the block. Although this concept is useful it is limitted in that there is no way to enforce the use of smart pointers to classes designed to be referenced by them. Thus if a user creates a class and intends that it should only be referenced via a "smart pointer" he must inform all the users of the class that they may not use normal pointers but must use his "smart pointer" class. If a programmer forgets and uses a normal pointer, then the program will not work and it will be very difficult to find the error. PURPOSE The following is a proposal for a language addition which would allow the user to declare a smart pointer to a class, and enforce its use by causing the compiler to transform all pointer declarations or expressions refering to that class to be instantiations of the smart pointer. PROPOSED SYNTAX Whereas "class T" is a declaration of T, "class *T" is a declaration of a "smart pointer" to T; If such a class is defined then the compiler is warned that a smart pointer to T exists and that all expresions and declarations which involve pointers to T (T*) should be converted to expresions or declarations involving the smart poitner (*T) instead. For example the following declaration: T *a; would be interpreted as: *T a; Or the following code segment: T x; T *p; p = &x; Would be interpreted as: T x; *T p; p = *T(x&); Thus a user can enforce the use of smart pointers without having to trust the memory of other users. The other users simply declare and use pointers to these objects normally without necessarily knowing that the pointers are in fact "smart pointers". DEFINING SMART POINTERS When in the scope of a *T definition, the use of pointer operations on type T are not converted to *T. Thus within the member functions of *T, pointers to T can be used normally. Thus: class *T { T *p; public: *T() {p = (T*)NULL;}; *T(T& t) {p = (T*)t;}; }; works alright because T* is a dumb pointer when in the context of the *T definition. Smart pointers to T can also be used in the scope of the *T definition, but they must be declared as *T; A definition of the form class *T{}; creates a dummy smart pointer which behaves exactly the way a dumb pointer does. It is a way of saying "I don't want a smart pointer to T." This is useful if you wish to cancel the inheritance of a smart pointer to a BASE CLASS. (See SMART POINTER INHERITANCE) CASTING SMART POINTERS Variables of type *T cannot normally be cast to pointer types. Specifically they cannot be cast to (void *). (Unless the conversion has been added as a member function operator void*()); Variables or expressions of type void* can be converted into *T by casting as follows: void *v; T *p; p = (T *)v; // converts void* into *T; This allows functions of the form: operator *T(void*) to be written so as to aid in the conversion from void* to *T; SMART POINTER INHERITANCE When a smart pointer *B has been declared for a class B, then any use of pointers to class D derived from B will use *B smart pointers unless a *D smart pointer has been declared. Thus: class B; class *B; class D : B; // D is derived from B D *p; // p is really a *B In the case of multiple inheritance, if one or more of the base classes has a smart pointer associated with it, it is illegal to use any pointer operations unless a smart pointer has been declared for the derived class: class A; class *A; // smart pointer to A class B; class D : A,B; // D is derived from A and B. D *p; // illegal unless *D is declared. SMART POINTERS AS CLASSES Smart pointers are true classes. They can have member data and functions. Can inherit from one or more base classes, etc. It seems likely that an inheritance hierarchy of classes would be shadowed by an inheritance hierarchy of smart pointers to those classes. REQUIRED MEMBER FUNCTIONS FOR *T CLASS DEFINITIONS *T() The default constructor does not exist. One must be defined with no parameters so that the compiler can create empty smart pointers. *T(T&) The pointerizing constructor. Used by the compiler to create pointers to existing objects. operator *() Should return a reference to an object of type T; operator ->() Must return a true pointer to type T. (Not a smart pointer) The compiler will not attempt to convert it to a smart pointer. RECOMMENDED MEMBER FUNCTIONS FOR *T CLASS DEFINITIONS operator[](int) Should return a reference to an object of type T; *T& operator+=(int) and *T& operator-=(int) Should perform reasonable transformations on the pointer and return references to *T (hopefully references to "this"). *T operator+(int) and *T operator-(int); friend *T operator+(int, *T&); Should perform reasonable transformations on the pointer and return a new *T; operator void*() Should return a void* 'v' which can properly be converted back to type *T via (T *)v CONCLUSION This technique could be a useful feature to the C++ language. It seems in character with other features of the language, and provides a way to control all indirect access to any type of object. -- +-Robert C. Martin-----+:RRR:::CCC:M:::::M:| Nobody is responsible for | | rmartin@clear.com |:R::R:C::::M:M:M:M:| my words but me. I want | | uunet!clrcom!rmartin |:RRR::C::::M::M::M:| all the credit, and all | +----------------------+:R::R::CCC:M:::::M:| the blame. So there. |