Generics 我可以避免使用泛型的trait实现的急于解决歧义吗?

Generics 我可以避免使用泛型的trait实现的急于解决歧义吗?,generics,rust,traits,Generics,Rust,Traits,考虑以下防锈代码[]: 据我所知,问题在于这里有一个模棱两可的地方——如果两者都是合法的,那么应该选择哪种实现?理想情况下,我希望有以下内容: 上面的代码(或一些变通方法)应该可以很好地编译 在调用站点,如果给定类型只有一个impl可能,则选择该类型 在呼叫站点,如果可能存在多个impls,则这是一个错误(一致性问题) 更简洁地说,我希望在调用站点而不是在定义站点完成歧义解决。有可能有这种行为吗 我可以避免使用泛型的trait实现的急于解决歧义吗 没有 是否可以在呼叫站点而不是定义站点进行[歧义

考虑以下防锈代码[]:

据我所知,问题在于这里有一个模棱两可的地方——如果两者都是合法的,那么应该选择哪种实现?理想情况下,我希望有以下内容:

  • 上面的代码(或一些变通方法)应该可以很好地编译
  • 在调用站点,如果给定类型只有一个
    impl
    可能,则选择该类型
  • 在呼叫站点,如果可能存在多个
    impl
    s,则这是一个错误(一致性问题)
  • 更简洁地说,我希望在调用站点而不是在定义站点完成歧义解决。有可能有这种行为吗

    我可以避免使用泛型的trait实现的急于解决歧义吗

    没有

    是否可以在呼叫站点而不是定义站点进行[歧义解决]

    没有


    有一个(长时间延迟)允许重叠的trait实现,但只有当其中一个实现比其他实现更具体时。我不相信这对你的情况是正确的,所以它不会有帮助

    另见:


      • 事实上,你可以在这里运用一个技巧

        为了让编译器为您选择一个
        impl
        ,它必须附加到一个可以推断的类型参数。您可以将类型参数添加到
        trait Foo
        并创建标记结构,以便
        impl
        s不再重叠:

        trait Foo<K, U> {
            const FOO: i32;
        }
        
        struct ByKeyInto;
        impl<K, K_, V> Foo<HashMap<K_, V>, ByKeyInto> for HashMap<K, V>
        where
            K: Hash + Eq + Into<K_>,
        {
            const FOO: i32 = 1;
        }
        
        struct ByValInto;
        impl<K, V, V_> Foo<HashMap<K, V_>, ByValInto> for HashMap<K, V>
        where
            K: Hash + Eq,
            V: Into<V_>,
        {
            const FOO: i32 = 2;
        }
        
        这张照片是()的:

        1
        2.
        

        然而,由于
        Into
        是自反的(也就是说,
        T
        为所有
        T
        实现
        Into
        ),如果您想为
        HashMap
        使用
        Foo
        ,这是很尴尬的。由于在这种情况下存在重叠的
        impl
        s,您必须通过turbofish选择一个(

        让z:HashMap=HashMap::new();
        叫我::(z);/印刷品1
        叫我::(z);/印刷品2
        
        在您的示例中是否可以选择单个实现?对于同一个类,您要求两个具有相同特性的实现,它们重叠,并且看起来都不比另一个更具体。我遗漏了什么吗?@9000假设
        V
        K
        有一些具体的类型,例如:(a)对于
        K
        没有
        ,以及(b)有一个唯一的
        V\u
        V:Into,那么应该选择第二个。你能提供一个如何使用的示例吗?我知道像这样的一些问题有解决办法,但我不知道它们是否适用于您的案例。@trentcl我在玩弄强制,您可能想“通过”任一参数进行强制。代码与此非常相似(现在不行,因为这不起作用),只是有一系列更多的特征约束。如果这里不行,那里也不行。也许我应该换个说法。在您理想的情况下,这里的代码被替换为(一些变通方法),调用站点是什么样子的?如果这段代码编译成功,你能写一个通过的测试吗?这段代码是否有任何与可靠性/模块性相关的问题?一些有根据的猜测对理解现状非常有帮助。我看了一下相关的问题,但我看不出这里的观点是如何适用的。我的问题不涉及重叠的impl,下游没有人可以为HashMap定义
        impl-Foo
        trait Foo<K, U> {
            const FOO: i32;
        }
        
        struct ByKeyInto;
        impl<K, K_, V> Foo<HashMap<K_, V>, ByKeyInto> for HashMap<K, V>
        where
            K: Hash + Eq + Into<K_>,
        {
            const FOO: i32 = 1;
        }
        
        struct ByValInto;
        impl<K, V, V_> Foo<HashMap<K, V_>, ByValInto> for HashMap<K, V>
        where
            K: Hash + Eq,
            V: Into<V_>,
        {
            const FOO: i32 = 2;
        }
        
        fn call_me<T, U>(_: T)
        where
            T: Foo<HashMap<String, i32>, U>,
        {
            println!("{}", T::FOO);
        }
        
        fn main() {
            let x: HashMap<&str, i32> = HashMap::new();
            call_me(x);
            let y: HashMap<String, bool> = HashMap::new();
            call_me(y);
        }
        
        let z: HashMap<String, i32> = HashMap::new();
        call_me::<_, ByKeyInto>(z);  // prints 1
        call_me::<_, ByValInto>(z);  // prints 2