I am trying to use the scoped!T() template to allocate inside the Program
class to save on an allocation. I can't get it working with the following exception.
Error: cannot cast &Scoped([void, void, void, void, void, void, void, void, void, void, void, void, void, void, void, void, void, void, void, void, void, void, void, void, void, void, void, void, void, void, void, void, void, void, void, void, void, void, void, void]).Scoped_store to ulong at compile time
I'm not shure if it is by design that one cannot use scoped for a class member or if it is an erorr in the scoped template. If its by design than this is a really crappy error message by the way.
The following code is to demonstrate my problem.
import std.typecons;
public class Foo
{
int i = 0;
}
public class Program
{
auto myFoo = scoped!Foo();
}
void main(string[] argv)
{
new Program();
}
auto myFoo = scoped!Foo();
This line will attempt to instantiate a Foo
class and initialize the myFoo
field during compilation. This is because scoped!Foo()
is interpreted as a default value, which are always computed during compilation, therefore the compiler attempts to interpret this expression (CTFE). Because scoped
does some low-level things to work, CTFE doesn't work in this case.
Instead, you should initialize the field at runtime, during class construction:
public class Program
{
typeof(scoped!Foo()) myFoo;
this()
{
myFoo = scoped!Foo();
}
}
The scoped
documentation actually covers this case. Quoting it:
Scoped member variables must have type
typeof(scoped!Class(args))
, and be initialized with a call to scoped. See below for an example.
And here is the referenced example:
class A
{
int x;
this() {x = 0;}
this(int i){x = i;}
~this() {}
}
// ...
// Use as member variable
struct B
{
typeof(scoped!A()) a; // note the trailing parentheses
this(int i)
{
// construct member
a = scoped!A(i);
}
}