Размышляя на досуге, пришёл к выводу, что большинство типов указателей, как существующих, так и новых, можно описать при помощи ограниченного набора атрибутов. Набор представлен ниже:
const — указатель не изменяемый, инициализация по месту объявления или в качестве аргумента функции;
no_addr — запрещает применение операции получения адреса к указателю; Используется для повышения возможностей оптимизатора.
auto_deref — упоминание идентификатора указателя равнозначно его разыменованию на месте "(*p)". Включает в себя no_addr. Для установки значения самого указателя используется специальный синтаксис (ключевое слово let, инициализация при объявлении в С++, аргумент функции);
fragile — "ломкий". Указатель на данные подлежащие скорому удалению. Семантика перемещения в С++;
not_null — гарантированно указывает на данные, проверка времени компиляции;
null_guard — проверка на неравенство нулевому указателю во время исполнения (в аргументах функций, при присвоении указателей без атрибута null_guard или not_null).
Теперь составим известные нам типы указателей из Ады, Паскаля, Оберона и С++ (pointer — просто указатель):
1) Указатель, к которому нельзя применить операцию взятия адреса:
typedef no_addr pointer ptr;
int x;
int ptr px = &x; // px = @x
&px // error
*px = 7; // можно оптимизировать до x = 7, px выбросить вообще
2) Автоматически разыменовываемый указатель
typedef auto_deref pointer ref;
int x;
int ref px; // px = @???
px = 1; // possible run-time crash
let px = &x; // px = @x
px = 1; // x = 1
3) Гарантированно указывающий на что-либо указатель
typedef not_null pointer ptr;
int x, y;
int ptr p; // compile time error
int ptr p = &x; // p = @x
p = &y; // p = @y
*p = 1; // y = 1
4) Гарантированно ненулевой указатель, проверка времени исполнения
typedef null_guard pointer ptr;
void Test (int ptr p) {}
iTest(nullptr); // run-time error
5) Семантика перемещения — функция принимает аргументом указатель на объект, который будет следом удалён
typedef fragile pointer ptr;
void Test (TObject ptr obj) {}
int *p = new int();
Test(p);
delete p;
6) VAR-параметр Оберона, Паскаля, Ады
typedef const auto_deref not_null pointer var;
procedure Test (var x: integer);
Test(1); // compile-time error
Test(x); // ok
Test(p^); // ok if p is pointer to integer
7) not null аргумент Ады, проверка времени исполнения
typedef not_null pointer ptr;
procedure Test (x: ptr integer);
Test(nil); // compile-time error
Test(@x); // ok
Test(p); // ok
8) Классические ссылки в С++
typedef const not_null auto_deref pointer &;
Примечание: возможность иметь ссылки на константы или возвращаемые по значению объекты есть синтаксический сахар, который можно с тем же успехом применить к любым пользовательским указателям в новой модели:
const int* p = 1; // p = @c1, c1 is const int, c1 = 1
TObject Test () {}
TObject* obj = Test(); // obj = @local1, local1 is TObject, @local1 передаётся функции теневым аргументом
Что думаете, господа?