On Tuesday, August 5, 2025 6:42:43 PM Mountain Daylight Time Brother Bill via 
Digitalmars-d-learn wrote:
> It doesn't seem like modern D needs the @disable feature.
>
> If a struct has a user provided constructor, then the default
> constructor is removed.

D structs don't really have default constructors. Types in general in D have
default initialization, which normally means that variables of that type are
initialized with their init value, which is determined at compile time. The
exception would be non-static nested structs which also have an implicit
context pointer, and those structs get default-initialized with their init
value _plus_ their context pointer gets initialized with the address of
their outer scope (whereas if you explicitly initialize such a struct with
their init value, you get a null context pointer). Either way, there is no
constructor involved. The compiler is blitting the type's init value into
the object's memory.

You can use S() to get the default-initialized value of a struct (which in
almost all cases is the same thing is S.init), but either way, it exists
whether you declare any constructors for a struct or not. Both

    S s;

and

    auto s = S();

will give you the default-initialized value of that struct, and that occurs
whether the struct has any constructors or not.

What you lose when you declare a constructor for a struct is the implicit
constructor syntax. That is, if you have something like

    struct S
    {
        int i;
        string s;
        bool b;
    }

then syntactically, it's like you have three different constructors,

    this(int)
    this(int, string)
    this(int, string, bool)

allowing you to "call" them with expressions such as S(42), S(19, "foo"),
and S(27, "bar", false). But the compiler doesn't actually give the struct
any constructors (e.g. when you list all of the members of such a struct, no
constructors are there). You just get the constructor syntax.

And when you declare any normal constructors (as opposed to something like a
copy constructor or postblit constructor), then you lose that syntax and can
only use the constructors which have been declared.

> Are there any cases where @disable is useful in modern D?

    @disable this();

will disable default initialization for a struct. So, then both

    S s;

and

    auto s = S();

will fail to compile. You're then forced to explicitly call a constructor to
initialize the struct.

Similarly,

    @disable this(this);

will disable copying a struct, and

    @disable void opAssign(S);

would disable the assignment operator for a struct.

In fact, you can use @disable on any symbol to make it so that it cannot
be used. In most cases, you'd just use it to disable something that the
compiler would normally automaticaly provide, but what it does in the
general case is allow you to have a symbol which will be found via symbol
resolution but which can't actually be used.

So, you could actually make it so that a struct couldn't be used with a
function via UFCS, because it had an @disabled member function with the same
name. Similarly, you could declare a variable and then make it unusable with
@disable. Whether that's actually useful in practice is debatable, but
@disable is a general mechanism which makes it so that a symbol exists but
isn't usable. It isn't restricted to a particular set of symbols.

But either way, at minumum, it's useful for disabling some of the symbols
that the compiler would normally generate automatically, giving you the
ability to do things like make a struct uncopyable or unassignable.

- Jonathan M Davis




Reply via email to