Hacker News new | ask | show | jobs
by siknad 1501 days ago

  template<typename T>
  concept has_foo = requires(T x){
  { x.foo } -> std::same_as<int>;
  };

  template<has_foo T>
  int get_foo(T x){...}

  // or

  template<typename T>
  requires has_foo<T>
  void f(T x){...}

  // or even

  void f(has_foo auto x) {...}
1 comments

Does the above provide more safety/guarantees/something than just:

type hasFoo interface {

  getfoo() int

  setfoo(int)
}

func f(hasFoo) {}

?

The equivalent Go would be something like:

    func f[T interface{.Foo}](T) {}
Of course, this doesn't exist in Go, so we must do:

    func f[T interface{GetFoo(); SetFoo()}](T) {}
And then define setters and getters on every type we want to use, including defining new types (with the commensurate setters/getters) for types that we don't own (i.e., if you import a struct from another package and it doesn't have setters and getters defined, you have to create a new type that implements those setters/getters).
I don’t know Go, but I think less in that concepts are syntax guarantees, not semantic guarantees. I suspect interfaces (assuming they are opt-in) are semantic guarantees. That said, I’ve never run into this distinction being a problem, and you could provide opt-in mechanisms in C++. Of course, the C++ interface has zero runtime cost.