| | 2257 | /** |
|---|
| | 2258 | Allocates a $(D class) object right inside the current scope, |
|---|
| | 2259 | therefore avoiding the overhead of $(D new). This facility is unsafe; |
|---|
| | 2260 | it is the responsibility of the user to not escape a reference to the |
|---|
| | 2261 | object outside the scope. |
|---|
| | 2262 | |
|---|
| | 2263 | Example: |
|---|
| | 2264 | ---- |
|---|
| | 2265 | unittest |
|---|
| | 2266 | { |
|---|
| | 2267 | class A { int x; } |
|---|
| | 2268 | auto a1 = scoped!A(); |
|---|
| | 2269 | auto a2 = scoped!A(); |
|---|
| | 2270 | a1.x = 42; |
|---|
| | 2271 | a2.x = 53; |
|---|
| | 2272 | assert(a1.x == 42); |
|---|
| | 2273 | } |
|---|
| | 2274 | ---- |
|---|
| | 2275 | */ |
|---|
| | 2276 | @system auto scoped(T, Args...)(Args args) if (is(T == class)) |
|---|
| | 2277 | { |
|---|
| | 2278 | struct Scoped |
|---|
| | 2279 | { |
|---|
| | 2280 | private ubyte[__traits(classInstanceSize, T)] Scoped_store = void; |
|---|
| | 2281 | @property T Scoped_payload() |
|---|
| | 2282 | { |
|---|
| | 2283 | return cast(T) (Scoped_store.ptr); |
|---|
| | 2284 | } |
|---|
| | 2285 | alias Scoped_payload this; |
|---|
| | 2286 | |
|---|
| | 2287 | this(Args...)(Args args) if (is(typeof(T.init.__ctor(args)))) |
|---|
| | 2288 | { |
|---|
| | 2289 | emplace!T(cast(void[]) Scoped_store, args); |
|---|
| | 2290 | } |
|---|
| | 2291 | |
|---|
| | 2292 | @disable this(this) { writeln("Scoped this(this)"); assert(false); } |
|---|
| | 2293 | |
|---|
| | 2294 | static if (is(typeof(T.init.__dtor()))) |
|---|
| | 2295 | { |
|---|
| | 2296 | ~this() |
|---|
| | 2297 | { |
|---|
| | 2298 | Scoped.__dtor(); |
|---|
| | 2299 | } |
|---|
| | 2300 | } |
|---|
| | 2301 | } |
|---|
| | 2302 | |
|---|
| | 2303 | static if (Args.length == 0) |
|---|
| | 2304 | { |
|---|
| | 2305 | byte[__traits(classInstanceSize, T)] result; |
|---|
| | 2306 | result[] = typeid(T).init[]; |
|---|
| | 2307 | static if (is(typeof(T.init.__ctor()))) |
|---|
| | 2308 | { |
|---|
| | 2309 | (cast(T) result.ptr).__ctor(); |
|---|
| | 2310 | } |
|---|
| | 2311 | return cast(Scoped) result; |
|---|
| | 2312 | } |
|---|
| | 2313 | else |
|---|
| | 2314 | { |
|---|
| | 2315 | return Scoped(args); |
|---|
| | 2316 | } |
|---|
| | 2317 | } |
|---|
| | 2318 | |
|---|
| | 2319 | unittest |
|---|
| | 2320 | { |
|---|
| | 2321 | class A { int x = 1; } |
|---|
| | 2322 | auto a1 = scoped!A(); |
|---|
| | 2323 | assert(a1.x == 1); |
|---|
| | 2324 | auto a2 = scoped!A(); |
|---|
| | 2325 | a1.x = 42; |
|---|
| | 2326 | a2.x = 53; |
|---|
| | 2327 | assert(a1.x == 42); |
|---|
| | 2328 | } |
|---|
| | 2329 | |
|---|
| | 2330 | unittest |
|---|
| | 2331 | { |
|---|
| | 2332 | class A { int x = 1; this() { x = 2; } } |
|---|
| | 2333 | auto a1 = scoped!A(); |
|---|
| | 2334 | assert(a1.x == 2); |
|---|
| | 2335 | auto a2 = scoped!A(); |
|---|
| | 2336 | a1.x = 42; |
|---|
| | 2337 | a2.x = 53; |
|---|
| | 2338 | assert(a1.x == 42); |
|---|
| | 2339 | } |
|---|
| | 2340 | |
|---|
| | 2341 | unittest |
|---|
| | 2342 | { |
|---|
| | 2343 | class A { int x = 1; this(int y) { x = y; } } |
|---|
| | 2344 | auto a1 = scoped!A(5); |
|---|
| | 2345 | assert(a1.x == 5); |
|---|
| | 2346 | auto a2 = scoped!A(); |
|---|
| | 2347 | a1.x = 42; |
|---|
| | 2348 | a2.x = 53; |
|---|
| | 2349 | assert(a1.x == 42); |
|---|
| | 2350 | } |
|---|