Оператор преобразования Node<T>::operator Node<T const>()
преобразует объект типа Node<T>
в объект типа Node<T const>
. Приведение (Node<T const>*)next
в этой функции и (Node<T const>*)node
в X
не являются преобразованиями между Node
объектами - они являются преобразованиями между указателями. Все, что происходит, это то, что адрес памяти объекта Node<T>
интерпретируется как адрес памяти Node<T const>
. В обоих случаях, однако, просто не a Node<T const>
по этому адресу памяти (если T
уже const
), поэтому указатели, полученные в результате приведений, являются «недействительными». Единственное, что вы можете сделать с полученными указателями, это привести их обратно к Node<T>*
(и даже это не гарантирует работу).
Ваш код a) никогда не вызывает определенный вами оператор преобразования и b) сломано. Результат x.getConst()
содержит недопустимый указатель, а доступ к *constX.node
является неопределенным поведением. Кроме того, если что-нибудь вызовет оператор преобразования, это создаст больше недействительных указателей. Если вы действительно хотите X<T const>
, то вы действительно должны скопировать все Node
s (и сделать это рекурсивно проще всего).
template<typename T>
Node<T>::operator Node<T const>() {
return {value, next ? new Node<T const>(*next) : nullptr};
// ^^^^^^^^^^^^^^^^^^^^ recursive call
}
template<typename T>
X<T const> X<T>::getConst() const {
return {new Node<T const>(*node)}; // I would suggest marking the constructor of X explicit
}
Лучше структурировать свой код так, чтобы вам просто не понадобилось , хотя, во-первых, это дорогостоящее преобразование.