[Solved] Rust how to make a C++ like * const pointer?

How can I implement the C++ *const pointer in Rust so that I can create a const struct pointer(Node *const head) but the struct field is mutable.

C++ example

class Node{
    int data;
}
class List{
private:
    Node *const head;
}

void List::insert(int key){
    Node* tmp = head; // I'm stuck with here.
    while(true){
        if (condition){
            tmp = some_node;
            break;
        }
        tmp = tmp->next();
    }
    tmp->data = key; // modify the field.
}

I tried to use let mut tmp_ptr: *mut Node<T> = &mut self.head; , but it will change the head node which is not I want.

A immutable borrow (&T) coerces into a *const T. Similarly a mutable borrow (&mut T) coerces into a *mut T.

fn takes_raw_const<T>(_: *const T) {}
fn takes_raw_mut<T>(_: *mut T) {}

fn main() {
    let foo = 0;
    
    takes_raw_const(&foo);
    takes_raw_mut(&mut foo);
}
1 Like

You're asking multiple different questions here.

  • * const: this doesn't exist in Rust. You cannot write Node *const head; in Rust.

  • *const T: this doesn't exist in C++, so it has no Rust equivalent.

  • Node *tmp = head; is just let mut tmp = self.head;.

  • "it will change the head node which is not I want": you can't modify the Nodes without having mutable access to the List.

It also doesn't help that your C++ code isn't complete, referring to things that don't exist.

If you want to implement a linked list, you should probably read Learning Rust With Entirely Too Many Linked Lists.

4 Likes

Here is an almost direct translation for reference, here is a more idiomatic rust version.

1 Like

I resolved it myself.

You should note that *const and *mut isn't that really different in Rust. They can trivially be convertible in both directions, even in safe context. *const doesn't guarantee about immutability, and *mut also doesn't do so about exclusive access. They're also treated equally in miri UB checker.

1 Like

See also What is the real difference between *const T and *mut T raw pointers?

1 Like

You're right, my way is to convert *const T pointer to * mut T pointer.

Thanks for your reply, I'm thinking a lot of the issues discussed here are important for beginners, so why not put them into the documentation?Or did I not find the correct document?

Except for FFI, beginners shouldn't be using raw pointers! The standard library has a wide number of safe, compostable abstractions for you to use, like Box, Rc, and RefCell.

In all my time writing rust I can only think of one time I've used raw pointers for something other than FFI, and that was to pair them with a PhantomData<&mut T> in some type that represented a mutable borrow of non-contiguous data (a matrix slice).

4 Likes

Thanks for your valuable advice.I'll try other standard way.