`BTreeSet` composite key

When I have BTreeSet<String>, I can check that it contains some string via let s: &str = ...; set.contains(s) - no clone involved. But if I have BTreeSet<(i32, String)>, I cant just set.contains((number, s)), I need set.contains(&(number, s.to_string()). Is there some way to avoid needless allocations and fulfill the use case?

As I see it, Borrow trait as a solution for maps is poor, as it is extremely limited.

You could use Cow<str> instead of String.

How? Cow requires a lifetime, but set needs to be 'static. But &str is not.

use std::borrow::Cow;
use std::collections::BTreeSet;

pub fn main() {
    let mut set: BTreeSet<(i32, Cow<str>)> = BTreeSet::new();
    
    set.insert((1, Cow::Owned("One".to_owned())));
    set.contains(&(1, Cow::Borrowed("One")));
}

You can do this with some dyn Trait tricks, but I think the coherence rules will require that you define your own key type instead of using a bare tuple.

3 Likes