Generics 除了使用带有关联常量的特征外,还有没有更简单的方法为泛型结构配备常量?

Generics 除了使用带有关联常量的特征外,还有没有更简单的方法为泛型结构配备常量?,generics,rust,constants,Generics,Rust,Constants,我有一个类型索引器,它可以向前(+1)或向后(-1)。在C++中: 枚举方向{ 向前地 向后的 }; 模板 结构索引器{ 静态constexpr int delta=(Dir==Forward?1:-1); }; void foo(){ 索引器f; } 这是我在Rust中实现此功能的最好方法: 使用std::marker::PhantomData; #[衍生(复制、克隆)] pub-struct-Forward; #[衍生(复制、克隆)] pub结构向后; 发布方向:复制{ 常数DELTA:i

我有一个类型
索引器
,它可以向前(+1)或向后(-1)。在C++中:

枚举方向{
向前地
向后的
};
模板
结构索引器{
静态constexpr int delta=(Dir==Forward?1:-1);
};
void foo(){
索引器f;
}
这是我在Rust中实现此功能的最好方法:

使用std::marker::PhantomData;
#[衍生(复制、克隆)]
pub-struct-Forward;
#[衍生(复制、克隆)]
pub结构向后;
发布方向:复制{
常数DELTA:i32;
}
前进的impl方向{
常数增量:i32=1;
}
向后的impl方向{
常数增量:i32=-1;
}
#[衍生(复制、克隆)]
发布结构索引器{
幻影数据,
}
impl索引器{
常数DELTA:i32=Dir::DELTA;
}
pub fn run(){
设idx=Indexer::{pd:PhantomData{};
}
PhantomData
似乎是必需的,因为我没有将
方向
存储在字段中,而这又需要大量的样板文件。有没有一种更简单的方法来移植C++代码?我希望避免宏或板条箱依赖关系。

这实际上取决于您在这里到底想做什么,但一个简化是:

#[derive(Copy, Clone)]
enum Direction {
    Forward = 1,
    Backward = -1,
}

impl Direction {
    const fn delta(self) -> isize {
        self as isize
    }
}
,也许更习惯地说,这可以写成

#[derive(Copy, Clone)]
enum Direction {
    Forward,
    Backward,
}

impl Direction {
    const fn delta(self) -> isize {
        match self {
            Self::Forward => 1,
            Self::Backward => -1,
        }
    }
}
或者你不能简单地把delta当作常数。在大多数情况下,编译器无论如何都会优化对它的out调用。只有当你真的需要结果是一个常量表达式时,它才是必要的

以下是如何使用此功能:

这真的取决于你在这里到底想做什么,但一个简化是:

#[derive(Copy, Clone)]
enum Direction {
    Forward = 1,
    Backward = -1,
}

impl Direction {
    const fn delta(self) -> isize {
        self as isize
    }
}
,也许更习惯地说,这可以写成

#[derive(Copy, Clone)]
enum Direction {
    Forward,
    Backward,
}

impl Direction {
    const fn delta(self) -> isize {
        match self {
            Self::Forward => 1,
            Self::Backward => -1,
        }
    }
}
或者你不能简单地把delta当作常数。在大多数情况下,编译器无论如何都会优化对它的out调用。只有当你真的需要结果是一个常量表达式时,它才是必要的

以下是如何使用此功能:


我想出了一些我在项目中使用的东西(直到rust支持const泛型):

我知道您想避免使用宏,但这个解决方案对我来说是相对可维护的,因为所有“静态值”(即const泛型参数)都是以相同的方式模拟的,它允许您临时定义和使用它们,并使用不同的类型,所有这些都是通过相同的体系结构实现的:只要您实际需要类型为
CG
的常量通用参数
Param
,就可以指定
Param:TStaticValue

您可能需要调整
define_static_value
以允许非
pub


关于
PhantomData
的备注:到目前为止,我没有找到一种方法来避免这些问题,但是您可以通过将所有未使用的参数打包到相应的字段中,确保每个结构体最多有一个
PhantomData
成员(然后会有类型
PhantomData

我想出了一些我在项目中使用的东西(直到rust支持const泛型):

我知道您想避免使用宏,但这个解决方案对我来说是相对可维护的,因为所有的“静态值”(即常量通用参数)以相同的方式进行模拟,它允许您通过相同的体系结构定义和使用不同类型的特殊参数:只要您实际需要类型为CG的常量泛型参数
Param
,就可以指定
Param:TStaticValue

您可能需要调整
define_static_value
以允许非
pub


关于
PhantomData
的备注:到目前为止,我没有找到一种方法来避免这些问题,但是您可以通过将所有未使用的参数打包到相应的字段中,确保每个结构体最多有一个
PhantomData
成员(然后会有类型
PhantomData

和不稳定的
const_泛型
特性,我将其写成:

//Rust 1.53.0-每晚(2021-03-28 4a20eb6a9da36c88ee92)
#![功能(常量泛型)]
#[派生(复制、克隆、PartialEq、Eq)]
枚举方向{
向前=1,
向后=-1,
}
#[衍生(复制、克隆)]
结构索引器{}
impl索引器{}
fn run(){
设idx=索引器::{};
}
由于Rust 1.51中仅提供const通用功能,您可以使用:

const-FORWARD:isize=1;
向后常数:isize=-1;
#[衍生(复制、克隆)]
结构索引器{}
impl索引器{}
fn run(){
设idx=索引器::{};
}

使用不稳定的
常量泛型
功能,我将其写成:

//Rust 1.53.0-每晚(2021-03-28 4a20eb6a9da36c88ee92)
#![功能(常量泛型)]
#[派生(复制、克隆、PartialEq、Eq)]
枚举方向{
向前=1,
向后=-1,
}
#[衍生(复制、克隆)]
结构索引器{}
impl索引器{}
fn run(){
设idx=索引器::{};
}
由于Rust 1.51中仅提供const通用功能,您可以使用:

const-FORWARD:isize=1;
向后常数:isize=-1;
#[衍生(复制、克隆)]
结构索引器{}
impl索引器{}
fn run(){
设idx=索引器::{};
}
define_static_value!(pub ForwardDelta, i32, 1);
define_static_value!(pub BackwardDelta, i32, -1);

pub struct Indexer<Dir: TStaticValue<i32>> {
    pd: std::marker::PhantomData<Dir>
}

impl<Dir: TStaticValue<i32>> Indexer<Dir> {
    const DELTA:i32 = Dir::VALUE;
}