| // run | |
| // Copyright 2021 The Go Authors. All rights reserved. | |
| // Use of this source code is governed by a BSD-style | |
| // license that can be found in the LICENSE file. | |
| package main | |
| import ( | |
| "fmt" | |
| "reflect" | |
| ) | |
| type Number interface { | |
| ~int | ~int8 | ~int16 | ~int32 | ~int64 | ~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 | ~uintptr | ~float32 | ~float64 | |
| } | |
| type MySlice []int | |
| type MyFloatSlice []float64 | |
| type _SliceOf[E any] interface { | |
| ~[]E | |
| } | |
| func _DoubleElems[S _SliceOf[E], E Number](s S) S { | |
| r := make(S, len(s)) | |
| for i, v := range s { | |
| r[i] = v + v | |
| } | |
| return r | |
| } | |
| // Test use of untyped constant in an expression with a generically-typed parameter | |
| func _DoubleElems2[S _SliceOf[E], E Number](s S) S { | |
| r := make(S, len(s)) | |
| for i, v := range s { | |
| r[i] = v * 2 | |
| } | |
| return r | |
| } | |
| func main() { | |
| arg := MySlice{1, 2, 3} | |
| want := MySlice{2, 4, 6} | |
| got := _DoubleElems[MySlice, int](arg) | |
| if !reflect.DeepEqual(got, want) { | |
| panic(fmt.Sprintf("got %s, want %s", got, want)) | |
| } | |
| // constraint type inference | |
| got = _DoubleElems[MySlice](arg) | |
| if !reflect.DeepEqual(got, want) { | |
| panic(fmt.Sprintf("got %s, want %s", got, want)) | |
| } | |
| got = _DoubleElems(arg) | |
| if !reflect.DeepEqual(got, want) { | |
| panic(fmt.Sprintf("got %s, want %s", got, want)) | |
| } | |
| farg := MyFloatSlice{1.2, 2.0, 3.5} | |
| fwant := MyFloatSlice{2.4, 4.0, 7.0} | |
| fgot := _DoubleElems(farg) | |
| if !reflect.DeepEqual(fgot, fwant) { | |
| panic(fmt.Sprintf("got %s, want %s", fgot, fwant)) | |
| } | |
| fgot = _DoubleElems2(farg) | |
| if !reflect.DeepEqual(fgot, fwant) { | |
| panic(fmt.Sprintf("got %s, want %s", fgot, fwant)) | |
| } | |
| } |