2017-01-11 2 views
6

Я пытаюсь сопоставить тип данных общего поля структуры и реагировать соответствующим образом. Моя общая идея была такой (не компилируется):Как совместить данные в Rust?

struct foo<T> { 
    zaz: String, 
    bar: T, 
} 

fn main() { 
    let x = foo::<String> { 
     zaz: "Hello".to_string(), 
     bar: "world".to_string(), 
    }; 
    let y = foo::<u32> { 
     zaz: "Hello".to_string(), 
     bar: 5, 
    }; 

    match x.bar { 
     String => println!("It's a string!"), 
     u32 => println!("It's a u32!"), 
     _ => println!("Something else"), 
    }; 

    println!("end of program!"); 
} 

Сообщение об ошибке от rustc:

error[E0001]: unreachable pattern 
    --> src/main.rs:18:9 
    | 
18 |   u32 => println!("It's a u32!"), 
    |   ^^^ this is an unreachable pattern 
    | 
note: this pattern matches any value 
    --> src/main.rs:17:9 
    | 
17 |   String => println!("It's a string!"), 
    |   ^^^^^^ 

error[E0001]: unreachable pattern 
    --> src/main.rs:19:9 
    | 
19 |   _ => println!("Something else"), 
    |  ^this is an unreachable pattern 
    | 
note: this pattern matches any value 
    --> src/main.rs:17:9 
    | 
17 |   String => println!("It's a string!"), 
    |   ^^^^^^ 

То, что я хотел, чтобы x соответствовать первый, и y, чтобы соответствовать второй. На самом деле я не уверен, что я хочу сделать, но что бы добиться желаемого эффекта?

+0

Короткий ответ «не сразу же». Вы можете найти этот вопрос полезным: [Как Rust реализует отражение?] (Http://stackoverflow.com/q/36416773/1233251) –

+0

Rust использует 'CamelCase' для структур, перечислений и признаков. Вы должны использовать 'Foo'. – Shepmaster

ответ

8

Идиоматического Решение

Создать признак, который ограничивает параметр T в foo, реализации какого-либо конкретное поведение в качестве ассоциированной функции данного признака.

Пример:

trait PrintMe { 
    fn print_me(&self); 
} 

impl PrintMe for String { 
    fn print_me(&self) { println!("I am a string"); } 
} 

struct Foo<T: PrintMe> { 
    zaz: String, 
    bar: T 
} 

fn main() { 
    // ... 
    x.bar.print_me(); 
} 

Это принципиален обобщенное программирование, где вы заявляете точно разницу поведения возможных общих параметров, так что нет ничего удивительного.


Точное решение

Ржавчина может действительно запрос типа: каждый тип имеет уникальный TypeId связанный, и вы можете соответствовать на TypeId с серией if проверок. Это неуклюже.

fn print_me<T>(x: &Foo<T>) { 
    if TypeId::of::<T>() == TypeId::of::<String>() { 
     println!("I am a string"); 
    } else // ... 
} 

Но пожалуйста ... не делай этого :)

+0

Спасибо, Маттье. Это проясняет ситуацию. Я думаю, мне нужно изменить свой дизайн в целом, я продолжаю выкладывать свой код «C style». Благодаря! – Dash83

+0

+1 для «не делай этого», и я просто укажу, что у Rust * есть * 'enum', который лучше (более короткий, более четкий, идиоматический и проверенный временем) способ записи всех этих' TypeId :: of'. – trentcl

+0

@trentcl: Это зависит. 'enum' для закрытого полиморфизма, тогда как' trait' для открытого полиморфизма ... если это имеет смысл. –