Фантомные параметры типа

Beginner

This tutorial is from open-source community. Access the source code

Введение

В этом лабораторном задании мы исследуем концепцию фантомных параметров типа, которые являются параметрами типа, проверяемыми статически во время компиляции и не имеющими никакого времени выполнения поведения или значений. Мы демонстрируем их использование в Rust, комбинируя std::marker::PhantomData с концепцией фантомных параметров типа для создания кортежей и структур, содержащих разные типы данных.

Примечание: Если лабораторная работа не уточняет имя файла, вы можете использовать любое имя файла, которое хотите. Например, вы можете использовать main.rs, скомпилировать и запустить его с помощью rustc main.rs &&./main.

Фантомные параметры типа

Фантомный параметр типа - это параметр, который не появляется во время выполнения, но проверяется статически (и только) во время компиляции.

Типы данных могут использовать дополнительные обобщенные параметры типа, чтобы действовать в качестве маркеров или для выполнения проверки типа во время компиляции. Эти дополнительные параметры не хранят значения и не имеют поведения во время выполнения.

В следующем примере мы комбинируем [std::marker::PhantomData] с концепцией фантомного параметра типа, чтобы создать кортежи, содержащие разные типы данных.

use std::marker::PhantomData;

// Фантомная структура кортежа, которая является обобщенной по `A` с скрытым параметром `B`.
#[derive(PartialEq)] // Позволяет проводить тест на равенство для этого типа.
struct PhantomTuple<A, B>(A, PhantomData<B>);

// Фантомная структура типа, которая является обобщенной по `A` с скрытым параметром `B`.
#[derive(PartialEq)] // Позволяет проводить тест на равенство для этого типа.
struct PhantomStruct<A, B> { first: A, phantom: PhantomData<B> }

// Примечание: Для обобщенного типа `A` выделяется память, но для `B` - нет.
//           Поэтому `B` нельзя использовать в вычислениях.

fn main() {
    // Здесь `f32` и `f64` - скрытые параметры.
    // Тип PhantomTuple задан как `<char, f32>`.
    let _tuple1: PhantomTuple<char, f32> = PhantomTuple('Q', PhantomData);
    // Тип PhantomTuple задан как `<char, f64>`.
    let _tuple2: PhantomTuple<char, f64> = PhantomTuple('Q', PhantomData);

    // Тип задан как `<char, f32>`.
    let _struct1: PhantomStruct<char, f32> = PhantomStruct {
        first: 'Q',
        phantom: PhantomData,
    };
    // Тип задан как `<char, f64>`.
    let _struct2: PhantomStruct<char, f64> = PhantomStruct {
        first: 'Q',
        phantom: PhantomData,
    };

    // Ошибка компиляции! Несоответствие типов, поэтому эти значения нельзя сравнить:
    // println!("_tuple1 == _tuple2 yields: {}",
    //           _tuple1 == _tuple2);

    // Ошибка компиляции! Несоответствие типов, поэтому эти значения нельзя сравнить:
    // println!("_struct1 == _struct2 yields: {}",
    //           _struct1 == _struct2);
}

Резюме

Поздравляем! Вы завершили лабораторную работу по Фантомным параметрам типа. Вы можете практиковаться в других лабораторных работах в LabEx, чтобы улучшить свои навыки.