View source code
Display the source code in std/typecons.d from which this page was generated on github.
Report a bug
If you spot a problem with this page, click here to create a Bugzilla issue.
Improve this page
Quickly fork, edit online, and submit a pull request for this page. Requires a signed-in GitHub account. This works well for small changes. If you'd like to make larger changes you may want to consider using local clone.

Template std.typecons.scoped

Allocates a class object right inside the current scope, therefore avoiding the overhead of new. This facility is unsafe; it is the responsibility of the user to not escape a reference to the object outside the scope.

template scoped(T) ;

The class destructor will be called when the result of scoped() is itself destroyed.

Scoped class instances can be embedded in a parent class or struct, just like a child struct instance. Scoped member variables must have type typeof(scoped!Class(args)), and be initialized with a call to scoped. See below for an example.

Contained Functions

NameDescription
scoped Returns the scoped object.

Note

It's illegal to move a class instance even if you are sure there are no pointers to it. As such, it is illegal to move a scoped object.

Example

class A
{
    int x;
    this()     {x = 0;}
    this(int i){x = i;}
    ~this()    {}
}

// Standard usage, constructing A on the stack
auto a1 = scoped!A();
a1.x = 42;

// Result of `scoped` call implicitly converts to a class reference
A aRef = a1;
writeln(aRef.x); // 42

// Scoped destruction
{
    auto a2 = scoped!A(1);
    writeln(a2.x); // 1
    aRef = a2;
    // a2 is destroyed here, calling A's destructor
}
// aRef is now an invalid reference

// Here the temporary scoped A is immediately destroyed.
// This means the reference is then invalid.
version(Bug)
{
    // Wrong, should use `auto`
    A invalid = scoped!A();
}

// Restrictions
version(Bug)
{
    import std.algorithm.mutation : move;
    auto invalid = a1.move; // illegal, scoped objects can't be moved
}
static assert(!is(typeof({
    auto e1 = a1; // illegal, scoped objects can't be copied
    assert([a1][0].x == 42); // ditto
})));
static assert(!is(typeof({
    alias ScopedObject = typeof(a1);
    auto e2 = ScopedObject();  // illegal, must be built via scoped!A
    auto e3 = ScopedObject(1); // ditto
})));

// Use with alias
alias makeScopedA = scoped!A;
auto a3 = makeScopedA();
auto a4 = makeScopedA(1);

// Use as member variable
struct B
{
    typeof(scoped!A()) a; // note the trailing parentheses

    this(int i)
    {
        // construct member
        a = scoped!A(i);
    }
}

// Stack-allocate
auto b1 = B(5);
aRef = b1.a;
writeln(aRef.x); // 5
destroy(b1); // calls A's destructor for b1.a
// aRef is now an invalid reference

// Heap-allocate
auto b2 = new B(6);
writeln(b2.a.x); // 6
destroy(*b2); // calls A's destructor for b2.a

Authors

Andrei Alexandrescu, Bartosz Milewski, Don Clugston, Shin Fujishiro, Kenji Hara

License

Boost License 1.0.