Home > OS >  In Go generics, why can't I use comparable constraint with order operators?
In Go generics, why can't I use comparable constraint with order operators?

Time:01-03

I am exploring go generics (1.18 beta), and have questions related to comparing two numerical values (a simple method that takes two values and returns a greater number).

For that, I am creating a custom numeric type that covers this type set (in the function getBiggerNumber):

int | int8 | int16 | int32 | int64 | float32 | float64

However, added one more function but this time instead of using a custom type had used a comparable built-in constraint (in the function getBiggerNumberWithComparable).

But below code gives an error on this method as

"invalid operation: cannot compare t1 > t2 (operator > not defined on T)"?

Any idea why the > operation did not work on built-in comparable types?

package main

import "fmt"

type numbers interface {
    int | int8 | int16 | int32 | int64 | float32 | float64
}

func getBiggerNumber[T numbers](t1, t2 T) T {
    if t1 > t2 {
        return t1
    }
    return t2
}

func getBiggerNumberWithComparable[T comparable](t1, t2 T) T {
    if t1 > t2 { // ./generics-sample.go:17:5: invalid operation: cannot compare t1 > t2 (operator > not defined on T)
        return t1
    }
    return t2
}

func main() {
    fmt.Println(getBiggerNumber(2.5, -4.0)) 
    fmt.Println(getBiggerNumberWithComparable(2.5, -4.0))
}

CodePudding user response:

comparable is the constraint for types that support equality operators == and !=. The generics proposal defines this in Comparable types in constraints:

To do this we introduce a new predeclared type constraint: comparable. The type set of the comparable constraint is the set of all comparable types. This permits the use of == and != with values of that type parameter.

Notably, this includes anything that can be used as a map key, including arrays, structs with comparable fields and interfaces that box comparable values.

It is true that in the Go language specifications, the comparison operators include order operators as (<, >, <=, >=). This choice of terminology probably is what confuses you. However the specs also disambiguate:

The equality operators == and != apply to operands that are comparable. The ordering operators <, <=, >, and >= apply to operands that are ordered.

Based on the current tip, the standard library constraint that supports the order operators such as > and < is constraints.Ordered, defined as:

type Ordered interface {
    Integer | Float | ~string
}
  • Related