C++ Logo

std-proposals

Advanced search

Re: [std-proposals] Generic code, not the API you are looking for

From: Jason McKesson <jmckesson_at_[hidden]>
Date: Fri, 19 Aug 2022 15:27:36 -0400
On Fri, Aug 19, 2022 at 2:07 PM Zhihao Yuan via Std-Proposals
<std-proposals_at_[hidden]> wrote:
>
> On Friday, August 19th, 2022 at 1:08 AM, Михаил Найденов via Std-Proposals <std-proposals_at_[hidden]> wrote:
>
> Hello,I am reading about efforts to improve generic code development, in particular introducing the so-called Customization Points/Functions. What is a bit odd to me is, the issue of the usage, of how the code looks, is not questioned. The fact something that should be a member function is now a free function, behind a specific namespace is not addressed. I am well aware of the reasons why (I think I read all the papers), but this does not change the fact, we stray more and more away from "Generic code is just normal code". Mind you, we did it already with type_traits - instead of querying the template type for an associated type, we need a "free function", in the form of type trait, to get that type. Once we go the same route with function calls, we basically given up on generic code being normal code:
>
> Normal code:
>
> void function(string s) {
> using char_t = string::char_type;
> // ...
> if(s.begins_with(something))
> { ... }
> }
>
> Generic form (optimistic in terms of syntax...)
>
> template<String S>
> void function(S s) {
> using char_t = stings::traits<S>::char_type; //< we need hoops
> // ...
> if(strings::begins_with(s, something)) //< we need hoops
> { ... }
> }
>
>
> It's a valid observation. The generic form could be
> as simple as
>
> generic<String S>
> void function(String s) {
> using char_t = String::char_type;
> // ...
> if(s.starts_with(something))
> { ... }
> }
>
> where even std::vector<char> can
> adapts to String protocol locally:
>
> override String for std::vector<char> {
> using char_type = char;
>
> bool starts_with(this auto const &v, std::string_view s) {
> return rg::starts_with(v, s);
> }
> }

I find ideas like this to be perplexing and highly limited and limiting.

First, I'm decidedly unsure about what... any of that actually is.
What is `String S` here? Is `String` a type concept? If so, what
happens if/when I need a "generic" based on a concept that takes more
than a single type parameter? And if it is a type concept, how does
`String::char_type` work? What is `S` doing, and why does `function`
take a `String` and not an `S`?

I'm guessing that you probably meant something like:

```
generic<String S>
void function(S s) {
  using char_t = S::char_type;
  // ...
  if(s.starts_with(something))
  { ... }
}
```

Does this `generic` declaration mean that if I have some type `T`
which happens to satisfy the concept `String`, there will
automatically be a function named `function` with that implementation?

Does the `override` declaration mean that `vector<char>::starts_with`
is a legitimate expression? Isn't that highly dangerous, as it
effectively allows you to modify a class's interface without actually
being the owner/maintainer of that type? What mechanism will exist
that will allow the owner/maintainer to add new interfaces in a way
that doesn't break some else's code?

Injecting definitions into a class without that class's explicit
knowledge and consent should be a non-starter.

Received on 2022-08-19 19:27:56