is my code to get CTFE instantiated object valid D ?

chmike via Digitalmars-d-learn digitalmars-d-learn at puremagic.com
Sat May 28 12:54:24 PDT 2016


On Friday, 27 May 2016 at 20:20:36 UTC, chmike wrote:
> I need to create an app wide singleton instance for my class.
> The singleton is immutable, but I want to allow mutable 
> references to that singleton object so that I can do fast 'is' 
> tests.
>
> I declared this
>
> class Category
> {
>      protected static immutable Category instance_ = new 
> Category;
>      Category instance() { return cast(Category)instance_; }
>      ...
> }
>
> It compiles and the instance should be instantiated at compile 
> time. I couldn't check yet.
>
> The public interface of Category is designed so that the 
> object's state can't be modified and thus remains immutable.
>
> Is this code valid D or is the behavior undefined due to the 
> cast ?
>
>
> A variant implementation would have a method that modifies the 
> object but only internally and in a very controlled way to 
> store strings in a cache for faster access. Would it still be 
> valid D code ?


I answer to myself on this question because I finally found out.

Creating an app wide singleton object is as simple as this

class Category
{
     this() { assert __ctfe); } // Just to make sure
     private __gshared instance_ = new Info;
     static Category instance() { return _instance; }
}


It works as long as the constructor doesn't reference other 
global or static variables.

Unfortunately this is what I have in my use case. I had this

final class Info
{
     Info(Category category, string name)
     {
         category_ = category;
         name_ = name;
         assert(__ctfe);
     }
     private string name_;
     private Category category_;
     string name() { return name_; }
     Category category() { return category_; }
}

This class can't be instantiated as compile time because the 
constructor depends on the global variable Category.instance_.

Category {
     ...
     __gshared Info a1 = new Info(Category.instance(), "I'm a1");
     __gshared Info a2 = new Info(Category.instance(), "I'm a2");
     ...
}


The problem is solved by changing Category into an immutable 
class and instance. It's Ok in my case because it is immutable. 
The only inconvenience left is that we can't have mutable 
references to immutable objects.

But at least now I can write

Info x1 = Cateqory.a1, x2 = Category.a2;
Info x3 = x1, x4;

assert(x3 is x1);
assert(x3 !is x2);
assert(x1.category is x2.category);
assert(x4 is null);

And of course we can also access all the properties of the Info 
values. Objects are identified by their unique address.

Another problem left is that synchronization


More information about the Digitalmars-d-learn mailing list