On Fri, 24 May 2013 07:57:51 -0400, Don <[email protected]> wrote:

On Friday, 24 May 2013 at 10:55:09 UTC, Artur Skawina wrote:
On 05/24/13 02:33, Steven Schveighoffer wrote:
On Thu, 23 May 2013 19:03:25 -0400, Artur Skawina <[email protected]> wrote:

On 05/23/13 23:06, Steven Schveighoffer wrote:

compiles:

struct S
{
   const int x;
   this(int n)
   {
    x = n;
   }
}

It's the 'const int x = 42;' case we're talking about. *That* one does not compile and doesn't need to. It /could/, but I see no reason to allow this;
 My example is essentially:
 const int x = 0;

No, that's not the same.
const int w;
is the same syntax used in C++. It's a declaration without an initializer. It signals your intention to initialize it later.

This isn't C++. C++ has implicit default constructors that are built using the given initializations. D does it differently.

Now, D does default-initialize everything, so that there really isn't any such thing as an uninitialized variable in D, but it still signals the intention that you will modify it later.

int is a misleading example since the default initializer is 0, and it's common for people to rely on that. Better to use char or float, or a class, where the default initializer is not usable, and it's clearer that it's a bug to use it.

OK, how about this:

struct MyFloat
{
   float f = 0.0;
}

struct S
{
   const MyFloat x;
}

:P

The only way I can understand this feature is that it is changing the meaning of initializers inside aggregates.

Previously, they were initializers. Now, they're not. They're setting the value of .init for the class.

This was ALWAYS the case.

struct S
{
   int x = 5; // sets S.init.x to 5
}

You are not looking at the change correctly. The change is simply, instead of const int x = 5 magically (and incorrectly) implying static, it doesn't. Then it defaults to the same behavior as non-const member initializers -- it sets the .init value for the struct. Previously, this was difficult to do, see my above example.

And they use the same syntax which is used for actual initializers.

They use the same syntax that is used to dictate the init value for non-const members.

In the past, the compiler didn't check if you from set a field in a constructor, which you had already initialized with an initializer.
But, it didn't really matter.
With a const field, it makes a much bigger difference, since if an initializer was specified, the only way that the field can make sense is if you modify it somewhere else. So the initializer MUST be able to be overwritten.

This has lead us to this oddity that under the new regime,

const char c = 'e';

is setting the value of c, unless it is inside an aggregate, in which case it's not initializing c, it's just specifying what .init is for that struct.

As is the same (and always has been) for all instance member initializers.

char c = 'e';

Hence, you are arguing for a change in behavior. And the arguments for that are extremely weak. The goal should be to allow const initialization to happen
exactly once.

I agree. This is the crux of the argument.
Are you and I the the only ones who see that as a valuable property of the language? I'm astonished that others are so willing to sacrifice it.

It's still available, just put static on the member, and it's the same as before.

-Steve

Reply via email to