2016-05-19 14 views
2

Rustで汎用パラメータ型のインスタンスを作成することはできますか?Rustで汎用関数の引数を使用して新しい変数を作成できますか?

実際の関数本体に型を作成するためにテンプレート型を使用するのが完全に有効なC++バックグラウンドから来ています。

この関数では、タイプTの変数を作成しようとしていますが、その方法はわかりません。

私はちょうど、タイプTのオブジェクトを作成し、それをロードし、その後、HashMapに挿入できるようにしたい:ここ

fn load<T>(&mut self, id: String, path: String) 
    where T: AssetTrait + 'static 
{ 
    // let asset : T = T; this doesn't work? 

    asset.load(path); 

    // self.assets.insert(id, Box::new<T>(asset)); 
} 

はすべて私のコードです:では

trait AssetTrait { 
    fn load(&self, path: String) { 
     // Do nothing 
     // Implement this in child asset object 
    } 
} 

struct AssetManager { 
    assets: HashMap<String, Box<AssetTrait + 'static>>, 
} 

impl AssetManager { 
    fn new() -> AssetManager { 
     let asset_manager = AssetManager { assets: HashMap::new() }; 

     return asset_manager; 
    } 

    fn load<T>(&mut self, id: String, path: String) 
     where T: AssetTrait + 'static 
    { 
     // let asset : T = T; this doesn't work? 

     asset.load(path); 

     // self.assets.insert(id, Box::new<T>(asset)); 
    } 
} 

答えて

4

C++では、T asset;のような変数を宣言すると、Tにデフォルトのコンストラクタ(コンパイル時のダックタイピングのバージョン)があると仮定しています。 Tをインスタンス化すると、デフォルトのコンストラクタを持たない型のコンパイルエラーですが、そのようなインスタンス化が行われない場合は問題ありません。

Rustでは、型パラメーターが操作をサポートしていると「仮定」することはできません。 typeパラメータには、サポートされている操作を境界で指定する必要があります。あなたはオプションに持っている、と述べた

は、例えばAssetTrait

の関連する機能のような独自のコンストラクタを定義し、あなたがselfパラメータを取ることはありません関連する関数としてloadを宣言することができますし、 Selfを返し、Tをインスタンス化するためにT::load(path)を呼び出します。

use std::collections::HashMap; 

trait AssetTrait { 
    fn load(path: String) -> Self; 
} 

struct AssetManager { 
    assets: HashMap<String, Box<AssetTrait + 'static>>, 
} 

impl AssetManager { 
    fn new() -> AssetManager { 
     let asset_manager = AssetManager { assets: HashMap::new() }; 
     return asset_manager; 
    } 

    fn load<T>(&mut self, id: String, path: String) 
     where T: AssetTrait + 'static 
    { 
     let asset = T::load(path); 
     self.assets.insert(id, Box::new(asset)); 
    } 
} 

錆に関連する機能

のようなコンストラクタを持って事前に定義された形質を使用し、Defaultトレイトは、この目的のために使用されます。

use std::collections::HashMap; 

trait AssetTrait { 
    fn load(&mut self, path: String); 
} 

struct AssetManager { 
    assets: HashMap<String, Box<AssetTrait + 'static>>, 
} 

impl AssetManager { 
    fn new() -> AssetManager { 
     let asset_manager = AssetManager { assets: HashMap::new() }; 
     return asset_manager; 
    } 

    fn load<T>(&mut self, id: String, path: String) 
     where T: Default + AssetTrait + 'static 
    { 
     let mut asset = T::default(); 
     asset.load(path); 
     self.assets.insert(id, Box::new(asset)); 
    } 
} 
+0

、私はそれが動作するようになったが、私は「資産」を変更しなければなりませんでした変数は、第2の例では、ロード関数が正しく機能するように変更可能である。 – John

+0

それは理にかなっています、 'load'は' self'を変更します。 – malbarbo

+2

細かい注記:implブロックでdecodeされたすべてのfnは、関連付けられたfnです。私たちは自己、メソッドを取る人のためのより具体的な名前を持っていますが、メソッドは関連する関数です。 –

関連する問題