34643


オペレータオーバーロードしたいです。単純な `Struct` ならいいのですが、 `Rc<Struct>` に `std::op::Add`
を実装させようとすると、コンパイルできません。解決策はあるでしょうか。

[code]

    use std::rc::Rc;
    use std::ops::Add;
    
    struct Struct;
    
    // コンパイルできない
    impl Add for Rc<Struct> {
        type Output = Rc<Struct>;
        fn add(self, rhs: Self) -> Self::Output {
            Rc::new(Struct{})
        }
    }
    
    // コンパイルできる
    impl Add for Struct {
        type Output = Struct;
        fn add(self, rhs: Self) -> Self::Output {
            Struct{}
        }
    }
    
    fn main() {}
    
[/code]

コンパイルエラーのメッセージは以下です。

[code]

    error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
      = note: the impl does not reference any types defined in this crate
      = note: define and implement a trait or new type instead
    
[/code]


CC BY-SA 3.0
2017-05-11T11:36:50.120
34639
2017-05-12T02:59:35.820
2017-05-12T02:59:35.820
18735
18735
question
rust
Rust: Rc<Foo> にトレイト std::op::Add を実装させたい


traitを実装する場合、型かtraitのどちらかが定義されているcrateである必要があるため、`Rc<Struct>`に`Add`を実装することは直接はできません。  
(なお、`impl Add<Struct> for Rc<Struct> {...}`のようなことは出来る）

よく行う代替手段としては、いわゆる[newtype pattern](https://github.com/rust-
unofficial/patterns/blob/master/patterns/newtype.md)と呼ばれる方法で、

[code]

    struct RcStruct(Rc<Struct>);
    
[/code]

のように型を新しく定義してその型に対して`Add`を実装します。このままだと`RcStruct`は`Rc`の関連関数を使えないので、`Deref`と`DerefMut`を実装しておきます。

[code]

    impl Deref for RcStruct {
        type Target = Rc<Struct>;
        fn deref(&self) -> &Self::Target {
            &self.0
        }
    }
    
[/code]

(`DerefMut`は略)加えて`Into`か`From`を実装しておくと`Rc::new(...).into()`で`RcStruct`を生成できます。

[code]

    impl Into<RcStruct> for Rc<Struct> {
        fn into(self) -> RcStruct {
            RcStruct(self)
        }
    }
    
[/code]

これで以下のように`Add`を実装します。

[code]

    impl Add for RcStruct {
        type Output = RcStruct;
        fn add(self, _rhs: Self) -> Self::Output {
            Rc::new(Struct {}).into()
        }
    }
    
[/code]


CC BY-SA 3.0
2017-05-11T17:02:12.400
34643
2017-05-11T17:02:12.400
9572
34639
answer