Допустим, я хочу представить двоичное дерево в C ++. Обычно я хочу структуру Node
, например:
struct Node {
Node* left
Node* right;
};
(здесь я использую struct и raw указатели просто для простоты. Я знаю, что я должен использовать умные указатели для управления памятью.)
У этого представления есть проблема: у меня никогда не может быть дерева с глубоким const
. (Поправьте меня, если смогу.) Я могу отметить один Node
const, но его дочерние элементы жестко закодированы как не-const
в структуре Node
.
(я могу использовать некоторые template
взломать left
и right
опционально const
, но это делает const Node
и non- const
Node
несовместимыми.)
Вскоре я узнал, если я волшебным образом имел некоторый указатель глубины const
(скажем, deep_const_pointer
, что делает const
ness транзитивным), я могу использовать этот указатель в Node
, так что наличие узла const
автоматически означает наличие субстанции const
tree.
Я попытался написать класс указателя deep- const
, и вот что я получаю в итоге:
template <typename T>
class deep_const_pointer {
public:
explicit deep_const_pointer(const T* p_)
: p{const_cast<T*>(p_)} {}
const T& operator*() const { return *p; }
T& operator*() { return *p; }
const T* operator->() const { return p; }
T* operator->() { return p; }
// etc.
private:
T* p;
};
Здесь я исключил const
в конструкторе и, необязательно, добавьте его обратно в соответствии с const
ness этого объекта, подобного указателю. Тем не менее, эта реализация допускает следующее:
const int i = 42;
deep_const_pointer<int> p{&i};
*p = 0; // Oops!
Таким образом, от пользователя зависит, правильно ли будет указывать, является ли указатель const
или нет.
Как мне построить Deep- const
указатель класса? В идеале я хочу, чтобы проверка const
происходила во время компиляции, и этот класс указателя занимает столько же памяти, сколько необработанный указатель. (Что исключает решение для сохранения const
ness в bool
переменной-члене и проверки при каждом доступе.)
EDIT : я проверил std::experimental::propagate_const
, и это на самом деле это не "глубокий" указатель с моей точки зрения. Я имею в виду глубокий константный указатель P
:
- Константа
P
является указателем на константу; - Изменяемый
P
является указателем на изменяемый; - Константная ссылка на неконстантную
P
обрабатывается так, как если бы она была константой P
; - Поскольку указатель на-const имеет семантику значений, const
P
должно быть тривиально копируемым.
propagate_const
не соответствует требованию, потому что:
- Он никогда не принимает указатель на константу;
- Это не подлежит копированию (конструкторы копирования явно удалены);
Судя по полученным комментариям и ответам, я думаю, что такой P
не реализуем в C ++.