如何定义函数的类型参数(或其相关类型)的函数本地类型别名? [英] How to define a function-local type alias of the function's type parameters (or their associated types)?

查看:97
本文介绍了如何定义函数的类型参数(或其相关类型)的函数本地类型别名?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个通用函数foo,具有一些复杂的特征界限:

I have a generic function foo with some complex-ish trait bounds:

use std::ops::Index;

// This trait is just as an example
trait Float {
    const PI: Self;
    fn from_f32(v: f32) -> Self;
}
// impl Float for f32, f64 ...

fn foo<C>(container: &C)
where
    C: Index<u32>,
    <C as Index<u32>>::Output: Float,
{
    // ...
}

我现在需要在一堆函数中使用类型<C as Index<u32>>::Output(例如,通过::PI或说::from_f32(3.0)来获取π).但是,这种类型很难手动输入,并且使整个代码非常冗长且难以阅读. (注意:在我的真实代码中,实际类型更长甚至更难看.)

I now need to use the type <C as Index<u32>>::Output inside the function a bunch (e.g. to get π via ::PI or say ::from_f32(3.0)). But this type is long to type out by hand and makes the whole code very verbose and hard to read. (Note: in my real code, the actual type is even longer and more ugly.)

为解决此问题,我尝试创建一个函数本地类型别名:

To solve this, I tried to create a function local type alias:

// Inside of `foo`:
type Floaty = <C as Index<u32>>::Output;

但这会导致此错误:

error[E0401]: can't use type parameters from outer function
  --> src/lib.rs:16:20
   |
10 | fn foo<C>(container: &C)
   |    --- - type variable from outer function
   |    |
   |    try adding a local type parameter in this method instead
...
16 |     type Floaty = <C as Index<u32>>::Output;
   |                    ^ use of type variable from outer function

因此,就像其他项目一样,type别名也将被处理,无论它们是否在函数中.没有什么好主意,我试图编写一个扩展为以下类型的宏:

So, just like other items, type aliases are also treated regardless of whether they are in a function or not. Not having any good ideas, I tried to write a macro that expands to the type:

// Inside of `foo`:
macro_rules! Floaty {
    () => { <C as Index<u32>>::Output };
}

Floaty!()::PI;    // errors

虽然我在此方面取得了部分成功(Floaty!()在某些类型上下文中有效),但最后一行错误如下:

While I had partial success with this (Floaty!() is valid in some type contexts), this last line errors with:

error: expected one of `.`, `;`, `?`, `}`, or an operator, found `::`
  --> src/lib.rs:20:14
   |
20 |     Floaty!()::PI;    // errors
   |              ^^ expected one of `.`, `;`, `?`, `}`, or an operator here

error[E0575]: expected method or associated constant, found associated type `Index::Output`
  --> src/lib.rs:17:17
   |
17 |         () => { <C as Index<u32>>::Output };
   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^
...
20 |     Floaty!()::PI;    // errors
   |     --------- in this macro invocation
   |
   = note: can't use a type alias as a constructor


我的尝试都没有完全奏效. 是否可以避免每次写出完整的类型名称?

推荐答案

柴油也有类似的问题",他们已经通过

Diesel has a similar "problem" and they've solved it by defining non-function-local type aliases. I like this solution because you can use the alias to clean up your trait bounds as well:

type Floaty<C> = <C as Index<u32>>::Output;

fn foo<C>(container: &C)
where
    C: Index<u32>,
    Floaty<C>: Float,
{
    let p = Floaty::<C>::PI;
    // ...
}

请注意,您必须更改特征Float以要求它为Sized才能真正运行此代码.

Note that you'll have to change your trait Float to require that it's Sized in order to actually run this code.

这篇关于如何定义函数的类型参数(或其相关类型)的函数本地类型别名?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆