Course contentsShow
← Rust
Lesson 611 of 1,9105. Type System and TraitsFree lesson

Abstracting Over Smart Pointers

Write generic code that operates on any container implementing the Deref trait.

In this lesson, you will learn how to write flexible functions that accept any type capable of behaving like a pointer, such as Box, Rc, Arc, or even simple references.

The Power of std::ops::Deref

In Rust, smart pointers are wrappers around data. While they have different memory management strategies—Box handles heap allocation, Rc manages reference counting—they all share one fundamental behavior: you can "dereference" them to access the underlying data.

This capability is governed by the Deref trait. Instead of hard-coding your functions to accept a specific type like Box<T>, you can write a generic function that requires the input to simply implement Deref.

Writing the Generic Function

Consider a scenario where you want a function that prints the length of a string, regardless of whether that string is stored in a Box, an Rc, or a standard reference.

use std::ops::Deref;

fn print_len<P>(pointer: P) 
where 
    P: Deref<Target = String>,
{
    // Because of Deref, we can access the String directly
    println!("Length: {}", pointer.len());
}

fn main() {
    let boxed = Box::new(String::from("Hello"));
    let reference = &String::from("World");

    print_len(boxed);
    print_len(reference);
}

Why This Matters

In the code above, P: Deref<Target = String> acts as a contract. It tells the compiler: "I don't care what the container is, as long as it knows how to reveal a String when dereferenced."

By using this abstraction, your code becomes significantly more reusable. You avoid forcing the caller to perform manual conversions (like calling .as_ref() or .clone()) just to satisfy your function's signature. This keeps your API clean and allows your logic to be "container-agnostic." You are focusing on the data being pointed to, rather than the management strategy of the pointer itself.

Key Takeaway: By using the Deref trait bound, you can write generic code that treats various smart pointers and references uniformly, decoupling your logic from specific memory ownership models.