template ctor overload Segmentation fault
Tejas
notrealemail at gmail.com
Tue Dec 14 13:02:16 UTC 2021
On Tuesday, 14 December 2021 at 12:04:36 UTC, RazvanN wrote:
> On Sunday, 12 December 2021 at 11:57:43 UTC, vit wrote:
>> [...]
>
> The problem is that the compiler will try to generate an inout
> copy constructor for Bar that looks roughly like this:
>
> ```
> this(ref scope inout(Bar) p) inout
> {
> this.foo = p;
> }
> ```
>
> The idea behind this lowering is to try and call the copy
> constructor for Foo object if possible. One issue here is that
> copy constructors have the same symbol name as constructors
> (__ctor), so `this.foo = p` gets lowered to `foo.__ctor(p)`.
> Since both the instance and the parameter are inout, the copy
> constructor of Foo cannot be called, so the templated
> constructor is called. After generating the template instance
> of the constructor, you end up with `this(scope inout(Foo))
> inout` ; that is basically an rvalue constructor. This is not
> valid code; if you write:
>
> ```
> struct Foo(T){
> //this(Rhs, this This)(scope Rhs rhs){}
> this(scope inout(Foo!int) rhs) inout {}
>
> this(ref scope typeof(this) rhs){
> }
> }
> ```
>
> You will get an error stating that you cannot define both an
> rvalue constructor and a copy constructor. However, since the
> constructor is templated it is impossible for the compiler to
> issue this error before actually instantiating the constructor.
> I see 2 possible fixes for this: (1) either we rename the copy
> constructor symbol to __cpCtor so that it does not clash with
> the normal constructor overload set or (2) when a templated
> constructor is instantiated, we can check whether it is an
> rvalue constructor and issue an error if a copy constructor
> exists.
>
> When I implemented the copy constructor I thought that it would
> better to have the copy constructor on a different overload set
> than the normal constructors, however, Walter insisted that
> they have the same name. So, I guess (2) is the way to go.
>
> Cheers,
> RazvanN
Then why did my modification work?
```d
struct Foo(T){
this(Rhs, this This)(scope Rhs rhs){
}
this(scope Foo!(T)* rhs){ //replaced typeof(this) with Foo!T
and ref with pointer. Code still works if I retain typeof(this)
}
}
struct Bar{
Foo!int foo;
}
void main(){
import std.stdio:writeln;
Bar bar = Bar();
auto BAR = new Bar();
writeln(bar, "\t", BAR, "\t", *BAR);
}
```
Did my modifications ensure that this is not treated as a copy
constructor?
More information about the Digitalmars-d-learn
mailing list