3 ms·
No, the equivalent go code would be package main import "fmt" type Yer[T any] interface { Y() T } func foo[V any, X Yer[V]](x X) V { re
by assbuttbuttass 2y ago
No, the equivalent go code would be
package main
import "fmt"
type Yer[T any] interface {
Y() T
}
func foo[V any, X Yer[V]](x X) V {
return x.Y()
}
type X struct {
y int
}
func (x X) Y() int { return x.y }
func main() {
xx := X{3}
fmt.Println(foo(&xx))
}
- cherryteastain 2y agoIt is not equivalent because, per the monomorphization discussion above, putting an interface in there means that you incur the cost of a virtual function call. The C++ code will compile down to simply accessing a struct member once inlined while the Go code you wrote will emit a ton more instructions due to the interface overhead.
- randomdata 2y agoDepending on which implementation you use, the following may produce the same instructions as the example above. Go on, try it! package main import "fmt" func foo(x *X) int { return x.y } type X struct { y int } func main() { xx := X{3} fmt.Println(foo(&xx)) } Now, gc will give you two different sets of instructions from these two different programs. I expect that is what you are really trying and failing to say, but that is not something about Go. Go allows devirualizing and monomorphizing of the former program just fine. An implementation may choose not to, but the same can be said for C++. Correct me if I'm wrong, but from what I recall devirtualization/monomorphization is not a requirement of C++ any more than it is of Go. It is left to the discretion of the implementer.
- cherryteastain 2y agoTried it out in godbolt, yes you are right that with the above example gc is able to realize that func foo[V any, X Yer[V]](x X) V can be called with only one type (X) and therefore manages to emit the same code in main_main_pc0. It all falls apart when you add a second struct which satisfies Yer [1], which leads the compiler to emit a virtual function table instead. You can see it in the following instructions in the code with a second implementation for Yer added: LEAQ main..dict.foo[int,*main.X](SB), DX LEAQ main.(*X).Y(SB), CX CALL CX [1] https://godbolt.org/z/zTco4ardx https://godbolt.org/z/zTco4ardx
- randomdata 2y agoWas it really necessary to try in gc...? We already talked about how it produces different instructions for the different programs. Nice of you to validate what I already said, I suppose, but this doesn't tell any of us anything we didn't already know. The intent was for you to try it in other implementations to see how they optimize the code.