2017-07-09 16 views
2

錆帳のI/O project exampleは、コマンドライン引数をクローニング示唆:インデックス可能なコレクションから一般にデータを移動する方法はありますか?

fn main() { 
    let args: Vec<String> = env::args().collect(); 
    let config = parse_config(&args); 
    // ... 
} 

struct Config { 
    query: String, 
    filename: String, 
} 

fn parse_config(args: &[String]) -> Config { 
    let query = args[1].clone(); 
    let filename = args[2].clone(); 

    Config { 
     query, filename 
    } 
} 

私はコピーを避けるために、Config構造体に値を移動したいと思います。

私は、スライスを移動しようとした:

fn parse_config(args: [String]) -> Config 

しかしエラーました:

the trait `std::marker::Sized` is not implemented for `[std::string::String]` 

それが今で無サイズ配列として読んでいるので、理にかなっています。

fn parse_config<T: std::ops::Index<usize, Output=String> + Sized>(args: T) -> Config 

エラーを与える:

cannot move out of indexed content 

それはinvalid stateにベクトルを残すだろうとしても、理にかなっている。この次はジェネリック医薬品を試してみました。

fn parse_config(mut args: Vec<String>) -> Config { 
    let query = args.remove(1); 
    // ... 

しかし、今の機能は、特定のコンテナVectorに結び付けられている:私はベクトルを移動することができます。

ベクトルを消費する関数を記述して、関数の一般的な性質を保持しながら、その内容を移動する方法を教えてください。

答えて

3

答えがかかりイテレータを使用することです:代わりに2で第二引数のインデックス作成のために、それが後に今一回の反復であるようにnth関数は、イテレータを進めると消費されていることを

... 
    let config = parse_config(args.into_iter()); 
    ... 

fn parse_config<T: Iterator<Item=String>>(mut args: T) -> Config { 
    let query = args.nth(1).expect("First arg none"); 
    let filename = args.nth(0).expect("Second arg none"); 
    ... 
} 

は注意、すなわち0

+1

'nth(0)'は通常 'next()'と書かれています。また、あなたの答えは、コレクションが「索引付け可能」であることとは関係がないことにも注意してください。 – Shepmaster

+0

上記の 'collect'と' into_iter'呼び出しの必要はありません。この関数に 'env :: args()'を直接渡すことができますか? –

関連する問題