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