Thread overview | ||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|
|
June 22, 2017 struct template constructors | ||||
---|---|---|---|---|
| ||||
Hi https://dpaste.dzfl.pl/0def4e286564 Is there a cleaner way to go than the one on the line 26? And why is the constructor /d475/f781.d(37): f781.UniquePtr!(A).UniquePtr.__ctor(DT)(ref scope UniquePtr!DT rhs) unfit for line 51? Is it because the expression " = UniquePtr!B.make()" cannot be interpreted as "scope ref"? It must release ownership of a pointer it holds, and looks like it cannot do it in this form. |
June 22, 2017 Re: struct template constructors | ||||
---|---|---|---|---|
| ||||
Posted in reply to Boris-Barboris | On 06/22/2017 12:06 PM, Boris-Barboris wrote: > Hi > > https://dpaste.dzfl.pl/0def4e286564 > > Is there a cleaner way to go than the one on the line 26? And why is the > constructor > > /d475/f781.d(37): f781.UniquePtr!(A).UniquePtr.__ctor(DT)(ref scope > UniquePtr!DT rhs) > > unfit for line 51? > Is it because the expression " = UniquePtr!B.make()" cannot be > interpreted as "scope ref"? It must release ownership of a pointer it > holds, and looks like it cannot do it in this form. (Going pedantic, you mean "struct constructor templates" or "templated struct constructors".) No time to think about the rest of the design but just to get the code compiled, replace 'ref' with 'auto ref' like so: this(DT)(scope auto ref UniquePtr!DT rhs) { // ... } Ali |
June 22, 2017 Re: struct template constructors | ||||
---|---|---|---|---|
| ||||
Posted in reply to Ali Çehreli | On Thursday, 22 June 2017 at 19:17:13 UTC, Ali Çehreli wrote:
> No time to think about the rest of the design but just to get the code compiled, replace 'ref' with 'auto ref' like so:
>
> this(DT)(scope auto ref UniquePtr!DT rhs)
> {
> // ...
> }
>
> Ali
i added this static variable:
static int destcalls = 0;
changed constructor to:
this(DT)(scope auto ref UniquePtr!DT rhs)
{
// here rhs releases pointer
pragma(msg, typeof(rhs));
}
wich prints "UniquePtr!(B)" on my machine,
and destructor:
~this() { destcalls++; }
Following code compiles and runs ok:
class A {}
class B: A {}
UniquePtr!A a = UniquePtr!A.make();
assert(destcalls == 0);
UniquePtr!A b = UniquePtr!B.make();
assert(destcalls == 1);
Destructor is called for the result of "UniquePtr!B.make();", and if it actually was passed by value (wich is indicated by pragma's output), b's internal pointer would refer to freed heap block.
|
June 22, 2017 Re: struct template constructors | ||||
---|---|---|---|---|
| ||||
Posted in reply to Ali Çehreli | On Thursday, 22 June 2017 at 19:17:13 UTC, Ali Çehreli wrote:
> No time to think about the rest of the design but just to get the code compiled, replace 'ref' with 'auto ref' like so:
Ok, looks like this indeed passes rhs by reference, thank you.
destcalls - number of times UniquePtr destructor was called
deallocs - number of times internal pointer was freed.
unittest
{
deallocs = destcalls = 0;
class A {}
class B: A {}
{
UniquePtr!B b = UniquePtr!B.make();
assert(b.owner);
{
UniquePtr!A a = b;
assert(!b.owner);
assert(a.owner);
assert(destcalls == 0);
assert(deallocs == 0);
}
assert(destcalls == 1);
assert(deallocs == 1);
}
assert(destcalls == 2);
assert(deallocs == 1);
}
|
June 22, 2017 Re: struct template constructors | ||||
---|---|---|---|---|
| ||||
Posted in reply to Boris-Barboris | On 06/22/2017 12:57 PM, Boris-Barboris wrote: > On Thursday, 22 June 2017 at 19:17:13 UTC, Ali Çehreli wrote: >> No time to think about the rest of the design but just to get the code >> compiled, replace 'ref' with 'auto ref' like so: > > Ok, looks like this indeed passes rhs by reference, thank you. To be complete, 'auto ref' passes lvalues by reference and rvalues by value, which you can detect with __traits(isRef): struct S{ } void foo()(auto ref S s) { static if (__traits(isRef, s)) { pragma(msg, "lvalue"); } else { pragma(msg, "rvalue"); } } void main() { auto s = S(); foo(s); foo(S()); } Ali |
June 22, 2017 Re: struct template constructors | ||||
---|---|---|---|---|
| ||||
Posted in reply to Ali Çehreli | On Thursday, 22 June 2017 at 20:05:46 UTC, Ali Çehreli wrote:
> To be complete, 'auto ref' passes lvalues by reference and rvalues by value, which you can detect with __traits(isRef):
>
> struct S{
> }
>
> void foo()(auto ref S s) {
> static if (__traits(isRef, s)) {
> pragma(msg, "lvalue");
> } else {
> pragma(msg, "rvalue");
> }
> }
>
> void main() {
> auto s = S();
> foo(s);
>
> foo(S());
> }
>
> Ali
Thank you very much! And the last question:
Is it guaranteed an all compilers, that:
1). destructor for said rvalue is called only once.
2). function taking auto ref parameter gets that exact (memory-wise) rvalue, for example:
struct S {}
S produce() { return S(); }
consume(produce());
void consume(auto ref S s)
{
// s passed by value, but is exactly that struct returned by produce, as if it
// was RVO'd inside consume's stack frame.
// and S destructor called only once on consume's scope escape?
}
|
June 22, 2017 Re: struct template constructors | ||||
---|---|---|---|---|
| ||||
Posted in reply to Boris-Barboris | On 06/22/2017 02:08 PM, Boris-Barboris wrote:
> On Thursday, 22 June 2017 at 20:05:46 UTC, Ali Çehreli wrote:
>> To be complete, 'auto ref' passes lvalues by reference and rvalues by
>> value, which you can detect with __traits(isRef):
>>
>> struct S{
>> }
>>
>> void foo()(auto ref S s) {
>> static if (__traits(isRef, s)) {
>> pragma(msg, "lvalue");
>> } else {
>> pragma(msg, "rvalue");
>> }
>> }
>>
>> void main() {
>> auto s = S();
>> foo(s);
>>
>> foo(S());
>> }
>>
>> Ali
>
> Thank you very much! And the last question:
> Is it guaranteed an all compilers, that:
> 1). destructor for said rvalue is called only once.
> 2). function taking auto ref parameter gets that exact (memory-wise)
> rvalue, for example:
>
> struct S {}
>
> S produce() { return S(); }
>
> consume(produce());
>
> void consume(auto ref S s)
> {
> // s passed by value, but is exactly that struct returned by produce,
> as if it
> // was RVO'd inside consume's stack frame.
> // and S destructor called only once on consume's scope escape?
> }
I'm not sure whether it's RVO or moving in what condition, but yes, there will be no copy. You will get the bit representation of the constructed object.
And yes, there should be one destructor, which may be a no-op if you grab its resource and set it to null.
On all compilers...
Ali
|
June 22, 2017 Re: struct template constructors | ||||
---|---|---|---|---|
| ||||
Posted in reply to Ali Çehreli | On Thursday, 22 June 2017 at 21:16:40 UTC, Ali Çehreli wrote:
> And yes, there should be one destructor, which may be a no-op if you grab its resource and set it to null.
>
> On all compilers...
That's a relief, thank you for your help.
|
June 23, 2017 Re: struct template constructors | ||||
---|---|---|---|---|
| ||||
Posted in reply to Boris-Barboris | On Thursday, 22 June 2017 at 21:19:43 UTC, Boris-Barboris wrote: > On Thursday, 22 June 2017 at 21:16:40 UTC, Ali Çehreli wrote: >> And yes, there should be one destructor, which may be a no-op if you grab its resource and set it to null. >> >> On all compilers... > > That's a relief, thank you for your help. > On all compilers... ... modulo bugs. Closely Related: https://github.com/dlang/dmd/pull/6852 |
June 23, 2017 Re: struct template constructors | ||||
---|---|---|---|---|
| ||||
Posted in reply to Petar Kirov [ZombineDev] | On Friday, 23 June 2017 at 00:54:36 UTC, Petar Kirov [ZombineDev] wrote: > On Thursday, 22 June 2017 at 21:19:43 UTC, Boris-Barboris wrote: >> On Thursday, 22 June 2017 at 21:16:40 UTC, Ali Çehreli wrote: >>> And yes, there should be one destructor, which may be a no-op if you grab its resource and set it to null. >>> >>> On all compilers... >> >> That's a relief, thank you for your help. > >> On all compilers... > > ... modulo bugs. > > Closely Related: https://github.com/dlang/dmd/pull/6852 And also: https://github.com/dlang/dmd/pull/6847/files#diff-89369a835b853bb3725fd1d10d9c2d5d |
Copyright © 1999-2021 by the D Language Foundation