8

I have something similar to this:

mod private {
    // My crate
    pub struct A;
    
    impl A {
        pub fn new() -> Self {
            Self
        }
        // ...
    }
}

fn main() {
    // External code
    let obj = private::A::new();
    let obj2 = private::A;
}

Currently, A doesn't need to store any internal state to do what I want it to (it's just being used as a placeholder in an enum), so I made it a zero-sized struct. However, that might change in the future, so I want to prevent code outside this crate from instantiating A without going through A::new() (i.e. the instantiation of obj2 in main() as it stands should fail).

Essentially, I want the same effect as if I'd added a private field to A, but I want it to remain zero-sized.

Currently, I'm thinking about something like this:

pub struct A {
    empty: (),
}

Or this:

pub struct A(());

However, I'm not sure which way is most idiomatic.

Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
anonymoose
  • 819
  • 2
  • 11
  • 25

1 Answers1

9

There is no established idiom for this. I'd use the tuple struct version:

pub struct A(());

Since the field is private, no one outside that module can construct A.

This is used inside the standard library:

pub struct Stdin(());
pub struct Stdout(());
pub struct Stderr(());

The standard library also uses the named field version:

pub struct Empty {
    _priv: (),
}

You could use any zero-sized type (e.g. a zero-length array or PhantomData), but () is the simplest.

See also:

Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366