Sign up ×

What's the difference between

enum i = 2;
enum s = "Hello";


immutable i = 2;
immutable s = "Hello";

in D 2.0?

share|improve this question

2 Answers 2

up vote 22 down vote accepted

An enum is a user-defined type, not a variable. enum e = 2; is a short-hand for something like this enum : int { e = 2 } (i.e. an anonymous enum with one member e), see the documentation. By definition, all members of an anonymous enum are placed into the current scope. So, e is a type member placed into the current scope, where it behaves like a literal. immutable i = 2; on the other hand actually creates a variable i of type int.

This difference has a couple of consequences:

  • enum e will have no memory location and no address (is no lvalue), since neither a type nor its members have an address. I.e. you cannot do something like auto ptr = &e; (just like you cannot do auto ptr = &2;). immutable i on the other hand is a normal variable (just immutable).
  • As discussed by Jonathan, immutable variables can be initialized at compile time or at run-time, whereas a type (with all its members defining the type) must be known at compile time.
  • The compiler can simply replace all appearances of e with 2. For i it usually has to create a memory location (although an optimizing compiler might be able to avoid this sometimes). For this reason, the workload during compilation for an enum might be expected to be somewhat lower, and the binary somewhat smaller.
  • There is a surprising difference for arrays. For enum uint[2] E = [0, 1]; and immutable uint[2] I = [0, 1]; the access to the enum, e.g. E[0], can be orders of magnitude slower than for the immutable array, e.g. I[0], especially as the arrays E and I get bigger. This is so because for an immutable array, it is just a normal array lookup to, say, a global variable. For the enum however it looks like the array gets created every time before it gets used, e.g. inside a function for a global enum (don't ask me, why, but the compiler really seems to simply replace the appearance with the value in this case, too). I have never tried but would guess that the same applies to enum strings and other non-trivial types.

To sum up: when I use compile-time constants, I usually take enum unless those constants are arrays or I need a memory location for some other reason.

share|improve this answer
+1 Interesting... thanks. – Mehrdad Jan 25 '11 at 17:00

enums are always initialized at compile time. So, they must be assigned values which can be created via CTFE (Compile Time Function Evaluation).

immutable variables can be initialized at runtime. If an immutable variable has a global lifetime (so it's a module variables or a static class or a static local variable), then it must be either be initialized at compile time or at runtime with a static constructor (though static local variables can't be assigned with a static constructor). If an immutable variable is a non-static local variable, then it's initialized at runtime (though if the value is a constant, then the compiler might optimize it and initialize it at compile time). So, you can create immutable local variables at runtime, unlike enums.

EDIT: One other case I forgot: immutable member variables must either be initialized directly with CTFE or initialized with an immutable constructor. If an immutable member varible is initialized directly with CTFE, then obviously that's done at compile time, whereas initializing it in an immutable constructor is done at runtime.

share|improve this answer
Yeah. Because that's not a valid CTFE expression. You can't currently use new with CTFE. It's not that advanced yet. – Jonathan M Davis Jan 25 '11 at 8:01
Wait, but then how do I make an immutable instance of an class? – Mehrdad Jan 25 '11 at 8:05
new immutable(Temp)() is fine. However, if it's a member variable, it must be done in an immutable constructor. You can't directly initialize an immutable class member variable, because directly initializing a member variable must be done with a value which is generated by CTFE, and you can't currently use new with CTFE. So, declare this(/*...*/) immutable {/*...*/} and initialize the member variable inside of it. – Jonathan M Davis Jan 25 '11 at 8:18
+1 Ah, okay, thanks. – Mehrdad Jan 25 '11 at 16:58

Your Answer


