为什么我要创建一个只有`PhantomData<()>` 成员的结构? [英] Why would I create a struct with only a `PhantomData&lt;()&gt;` member?

查看:33
本文介绍了为什么我要创建一个只有`PhantomData<()>` 成员的结构?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在阅读另一个问题的答案时,我看到了这个结构 [1]:

While reading the answer for another question, I saw this construct [1]:

struct Clipboard {
    marker: PhantomData<()>,
}

虽然我见过 PhantomData,它们都被参数化为一个有趣的类型,比如 PhantomData<&'a [u8]>PhantomData.为什么要创建 行为 就好像它包含一个空元组一样的结构?

While I've seen other uses of PhantomData, all of them have been parameterized with an interesting type, like PhantomData<&'a [u8]> or PhantomData<T>. Why would you want to create struct that acts as if it contains an empty tuple?

[1]:有点诗意,因为我实际上写了另一个答案,但被要求解释我为什么这样做.评论太长了.

[1]: A bit of poetic license as I actually wrote the other answer, but was asked to explain why I did what I did. It was too long for a comment.

推荐答案

在这种情况下,剪贴板是一个全局共享的资源,当您打开它时不会给您任何令牌.在不先打开剪贴板的情况下尝试使用剪贴板将是一件坏事.如果你做了简单的事情并创建了一个空结构,那么你可能忘记调用正确的构造方法:

In this case, the clipboard was a globally shared resource that didn't give you any token when you opened it. To try and use the clipboard without opening it first would be a Bad Thing. If you did the straightforward thing and created an empty struct, then you could forget to call the proper constructor method:

struct Clipboard;

impl Clipboard {
    fn new() -> Clipboard {
        println!("Clipboard opened");
        Clipboard
    }

    fn copy(&self) -> String { "copied".into() }
}

let c = Clipboard::new(); // Correct
println!("{}", c.copy());
let c = Clipboard;        // Nope, didn't open the clipboard properly
println!("{}", c.copy()); // But can still call methods!?!?!

让我们尝试一个包含虚拟值的元组结构:

Let's try a tuple struct with a dummy value inside:

struct ClipboardWithDummyTuple(());

impl ClipboardWithDummyTuple {
    fn new() -> ClipboardWithDummyTuple {
        println!("Clipboard opened");
        ClipboardWithDummyTuple(())
    }

    fn copy(&self) -> String { "copied".into() }
}

let c = ClipboardWithDummyTuple::new(); // Correct
println!("{}", c.copy());
let c = ClipboardWithDummyTuple;
println!("{}", c.copy()); // Fails here
// But because `c` is a method, not an instance              

这样更好,但错误发生的时间比我们希望的要晚;它只在我们尝试使用剪贴板时发生,而不是在我们尝试构建它时发生.让我们尝试使用命名字段创建一个结构体:

This is better, but the error occurs later than we'd like; it only happens when we try to use the clipboard, not when we try to construct it. Let's try making a struct with named fields:

struct ClipboardWithDummyStruct { 
    // warning: struct field is never used
    dummy: (),
}

impl ClipboardWithDummyStruct {
    fn new() -> ClipboardWithDummyStruct {
        println!("Clipboard opened");
        ClipboardWithDummyStruct { dummy: () }
    }

    fn copy(&self) -> String { "copied".into() }
}

let c = ClipboardWithDummyStruct::new(); // Correct
println!("{}", c.copy());
let c = ClipboardWithDummyStruct; // Fails here
// But we have an "unused field" warning

所以,我们更接近了,但这会生成关于未使用字段的警告.我们可以#[allow(dead_code)]关闭该字段的警告,或者我们可以将该字段重命名为_dummy,但我相信有更好的解决方案 - PhantomData:

So, we are closer, but this would generate a warning about an unused field. We could turn off that warning for the field with #[allow(dead_code)], or we could rename the field to _dummy, but I believe there's a better solution — PhantomData:

use std::marker::PhantomData;

struct ClipboardWithPhantomData { 
    marker: PhantomData<()>,
}

impl ClipboardWithPhantomData {
    fn new() -> ClipboardWithPhantomData {
        println!("Clipboard opened");
        ClipboardWithPhantomData { marker: PhantomData }
    }

    fn copy(&self) -> String { "copied".into() }
}

let c = ClipboardWithPhantomData::new(); // Correct
println!("{}", c.copy());

let c = ClipboardWithPhantomData; // Fails here

这不会产生任何警告,并且 PhantomData 用于指示正​​在发生不同"的事情.我可能会对 struct 定义发表一点评论,以说明我们为什么以这种方式使用 PhantomData.

This doesn't generate any warnings, and PhantomData is used to indicate that something "different" is happening. I'd probably throw a little comment on the struct definition to note why we were using PhantomData in this way.

这里的很多想法都源于一个半相关的关于正确类型的 Rust 问题用于不透明结构.

A lot of the ideas here stem from a semi-related Rust issue about the correct type for an opaque struct.

这篇关于为什么我要创建一个只有`PhantomData<()>` 成员的结构?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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