1. 4
  1.  

  2. 1

    Not going to answer on SO because I don’t want to put the work in, but:

    Sure, you could generalize a function by allowing for structural subtypes on contravariant type variables and structural supertypes on covariant type variables, but this is a bad idea. If the user didn’t specifically request that the function work on anything of the right structural type, they probably had a specific semantics in mind that’s unique to the nominal type they did specify.

    1. 1

      It sounds like what you’re describing is similar to how interface types work in Go, although they’re polymorphic only over methods, not fields like in your example. If you have a “struct” (these are C++‘s structs, not C’s structs; they have a vtable attached) like

      type Foo struct {
          Name string
      }
      

      And a getter:

      func (f Foo) GetName() string {
          return f.Name
      }
      

      Then you can call this function with a value of type Foo:

      func GetNameFromAnything(thing interface { GetName() string }) string {
          return thing.GetName();
      }
      

      Like this:

      func main() {
          f := Foo{Name: "maxhallinan"}
          fmt.Printf("%s\n", GetNameFromAnything(f));
      }
      

      Go is almost statically duck-typed; you can, in-line, say “this method takes anything that can give me its name,” et voila. The biggest downside, I think, and the biggest difference between what you asked in your question and Go, is that access to these members is mediated through a vtable. Because vtables only contain methods in Go, you have to write getters for the things you want to be able to access through interfaces, so there’s no true way to say “this method takes anything that has a field called Name on it”.