On Sat, Aug 20, 2022 at 6:52 PM Zhihao Yuan via Std-Proposals <std-proposals@lists.isocpp.org> wrote:
On Saturday, August 20th, 2022 at 6:27 AM, Jason McKesson via Std-Proposals <std-proposals@lists.isocpp.org> wrote:
> > In the protocols/generics model "the concept" is an entity by itself, much like Zhihao said. Inside func, the code will actually ask String itself for methods, not directly the class that it is instantiated with.
> That ship sailed when C++20 standardized a concept model that was
> fundamentally incapable of definition checking. C++20 concepts are
> exactly and only a way to constrain a template declaration, nothing
> more. And there's no simple way to turn them into something more.

I don't know why "concept model" is brought
up here. [...]

Well, as I understand it, Jason was interpreting your suggested "protocol" paradigm as a tweak to the existing C++20 Concepts paradigm (which it definitely can't be); it seems more likely to me that you intended it as Yet Another Paradigm in the multi-paradigm language that is C++. So if we allowed "protocols," then we'd have at least three competing/coexisting paradigms for polymorphic programming:
- classical inheritance-based polymorphism
- templates (i.e. unconstrained or constrained, but in either case not C++0x "concept maps")
- "protocols" (i.e. Go interfaces, type erasure) <— this new thing

Jason wrote:
> what happens if/when I need a "generic" based on a concept that takes more than a single type parameter? 

Type erasure is based on unary interfaces by definition. It simply cannot handle STL-style webs of interrelationships between T, T::value_type, T::iterator, T::const_iterator, and so on. It doesn't work for that stuff. So "protocols" wouldn't be attempting to replace STL-style templates; "protocols" would just be yet another paradigm that programmers could choose to use or not.
(Now, I think having too many paradigms is a bad thing; but I recognize that that argument holds little water, because the "having too many paradigms" ship sailed in C++ sometime in the mid-1990s. ;))

It does occur to me that if all you want is "concept maps," you can get that today via basically the same mechanism that gave us std::string_view: write an adaptor that takes in a "suitably string-like" type and spits out an actually string-like type.  It's very fiddly today, though, I admit.

    std::string_view StringLikeOf(const std::vector<char>& v) {
      return std::string_view(v.data(), v.size());
    template<StringLike S>
    const S& StringLikeOf(const S& s) { return s; }

    template<StringLike S>
    void function(const S& sx) {
      decltype(auto) s = StringLikeOf(sx);
      [...use (s) instead of (sx)...]

For the difficulties that would be caused by any attempt to "half-do" concept maps, the background reading I know of includes

(One problem is basically that
    protocol String {
        bool startswith(std::string s) const;
now forces `myString.startswith("hello")` to construct a `std::string` argument object, even when the original type would have known how to do the operation on a `const char*` more efficiently. Flattening overload sets in that way is usually not beneficial to performance. It has other advantages; but performance is not one of them.)


my $.02,