On Monday, 5 October 2015 at 10:57:57 UTC, Shachar Shemesh wrote:
On 05/10/15 13:39, Marc Schütz wrote:
On Monday, 5 October 2015 at 09:25:30 UTC, Shachar Shemesh wrote:
What's more, init is used even if you @disable this(). The following
compile and does what you'd expect (but not what you want):
struct S {
   int d;

   @disable this();
   this( int d ) {
      this.d = d;
   }
}


...

   S d = S.init;

I don't understand this. How is that not what you want, considering that
you explicitly told it to use the init value?

One of the basics of C++ is that, if you construct the type correctly, then the user of the type cannot use it in a way that will cause inconsistencies. Such a use will not compile.

The above shows that you cannot construct such a type in D. The language simply does not allow you to cancel a certain feature of the type in which you are uninterested.

`@disable this();` works fine to prevent the user from doing that accidentally. But in your example, this doesn't happen by accident; you explicitly told the compiler to use the .init value. That's not something you do just because you can, you need to have a reason for it. Presumably a user doing this would know what they're doing.

I don't think it's reasonable to expect to be able to prevent that, just as you can't forbid the user to do unsafe casts. And arguably, if your type's .init is invalid, then "you're doing it wrong".

Besides, that every type has a .init value is a very fundamental part of the language, not just a feature of a particular type. Sure, you use some flexibility for edge cases, but IMO that's a good tradeoff for the general advantages you gain from it.


Please bear in mind that the init might not be called directly. Programmer A defines a type that should never be uninitialized (i.e. - needs a constructor). Programmer B places an instance of that type inside a containing struct. Programmer C uses that containing struct's init. Such a problem is not easy to catch, even if programmers A, B and C are the same person.


If you use normal declaration, the compiler correctly rejects that:

struct A { @disable this(); }
struct B { A a; }
void main() { B b; }

// Error: variable xx.main.b default construction is disabled for type B

If you'd use B.init, of course you'd get exactly what you ask for, see above.

Reply via email to