2015-10-20 46 views
2

我想要实现的一些具体功能的自定义特征,即实施性状FN型

trait ToTarget { 
    fn custom_str(&self) -> String; 
} 

impl ToTarget for fn() -> String { 
    fn custom_str(&self) -> String { 
     self() 
    } 
} 

impl ToTarget for fn(i32) -> String { 
    fn custom_str(&self) -> String { 
     self(4) 
    } 
} 

fn a() -> String { 
    "abc".to_string() 
} 

fn b(x: i32) -> String { 
    x.to_string() 
} 

fn main() { 
    println!("{}", b.custom_str()); 
} 

然而,这并不编译给下一个错误:

<anon>:26:22: 26:34 error: no method named `custom_str` found for type `fn(i32) -> collections::string::String {b}` in the current scope 
<anon>:26  println!("{}", b.custom_str()); 
           ^~~~~~~~~~~~ 
note: in expansion of format_args! 
<std macros>:2:25: 2:56 note: expansion site 
<std macros>:1:1: 2:62 note: in expansion of print! 
<std macros>:3:1: 3:54 note: expansion site 
<std macros>:1:1: 3:58 note: in expansion of println! 
<anon>:26:5: 26:36 note: expansion site 
<anon>:26:22: 26:34 help: items from traits can only be used if the trait is implemented and in scope; the following trait defines an item `custom_str`, perhaps you need to implement it: 
<anon>:26:22: 26:34 help: candidate #1: `ToTarget` 
error: aborting due to previous error 
playpen: application terminated with error code 101 

但是,如果我指定b代码编译的类型:

println!("{}", (b as fn(i32) -> String).custom_str()); 

所以问题是:有没有办法让我的第一个版本sion of code

println!("{}", b.custom_str()); 

compile?每次我想要使用我的特质时指定函数的类型真的很烦人。

回答

2

问题是每个函数都有它自己的类型,但可能与另一个函数具有相同的签名。您对签名为fn(i32) -> String的所有功能实施了特征ToTarget

举例:您的函数b的类型为fn(i32) -> collections::string::String {b}(请注意类型中的{b}),但不能明确指定此类型。

你可以做的是落实ToTarget为实现Fn(i32) -> String所有类型:

trait ToTarget { 
    fn custom_str(&self) -> String; 
} 

impl<T> ToTarget for T where T: Fn(i32) -> String { 
    fn custom_str(&self) -> String { 
     self(4) 
    } 
} 

fn b(x: i32) -> String { 
    x.to_string() 
} 

但你无法实现ToTargetFn() -> String或任何其他类型的对于这个问题,因为有可能是一个类型实现Fn(i32) -> StringFn() -> String,这将产生相同类型的两种不同的实现。据我所知,即使impl specialization在这里也没有帮助,所以你运气不好。

+1

我不确定这会产生什么样的效果,但是确保具有相同签名的所有功能都可以强制进入该签名是一件容易的事情。 –

+0

感谢您的回答。我的第一个尝试是为'Fn'特性实现'ToTarget',但是一旦我写了第二个实现,我发现我不能第二次实现ToTarget特性。我想我会在这种特殊情况下切换到宏。 –