C++ Logo

std-proposals

Advanced search

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

From: Михаил Найденов <mihailnajdenov_at_[hidden]>
Date: Tue, 30 Aug 2022 18:51:37 +0300
On Mon, Aug 29, 2022 at 6:32 PM Arthur O'Dwyer <arthur.j.odwyer_at_[hidden]>
wrote:

> On Sat, Aug 27, 2022 at 11:21 AM Михаил Найденов via Std-Proposals <
> std-proposals_at_[hidden]> wrote:
>
>> Hello again,
>> I ended up writing a small proposal on this topic as I am quite bothered
>> with the issue.
>> Attached is the draft
>>
>
> Hi Mikhail,
> I looked at your paper. I think it needs to use the words "concept maps"
> somewhere in the paper: that's basically what you're proposing as a
> solution, but the paper doesn't show any evidence that you've dug into the
> previous proposals and why they failed.
>

Hello,
I am deliberately not providing, or investigating, a solution mainly
because there is no simple one, much like you explained in Your previous
post. What is the point discussing concept_maps when we don't have checked
concepts, concept preservation, nominal conformance?
The proposal is a top-down view of what I believe is desirable by many - to
have generic code that works on all/external types and does not require
effectively a rewrite of the original algorithm and/or extensive planning
just because it is generic.


>
> Then, at a higher level, you have not convinced me that there's any
> problem here at all! Your original, "just programming," version of your
> function looks like this (quote):
>
> void silly(string& s) <https://mail-attachment.googleusercontent.com/attachment/u/0/?ui=2&ik=aba66a32fc&attid=0.1&permmsgid=msg-f:1742328244751920533&th=182dfe4eae916d95&view=att&disp=inline&realattid=f_l7c1rr8i0&ser=1&saddbat=ANGjdJ_qVCrD5VtcwzbDcbDVeAnx9f6fofNi6MFWBJgCz-kQlYEx_Pci4UMbG80BfeZubUoYMz555AJPQ_GQrjr1ylClW6FqsctQ_q9XwxnECGc81qd5v9ZsHPBye9abZ-z7F7s332ZLrcB7CqT6cVZ1BQ9yCdbUq_emtRQoW08fcluey9zkq9TpCjACPnHj69Kj3ykd0TDz3R_IQSMVrbVu2zG1SqoLnMr0I5IpP_0zdYFUMc5KirVALGeMo2YEX88TwkuGnNreTra-tRooWHcf75Kyc4vKrW4Ym8y22tNpMsTABG7cL6eRiIwS03xUXiyTrUrbhv8rm42IQ22TU9ksCz8NqnLGMoiAdoeh1kxGPQtHPZM6QKWr-m19Gi-wZcnhpF-jiO6_U8t9meAQ6LxERVXj7oDZbSrEtH7C99YSbe_qBEWYCnIWFNMvd5LmsCagaWKn_QdXj_sp9i9sprmVhjRCWaW3uDgNYCE0dZnsLfec2uUAtbtytxYnk5oGjEXHtJuTyT7QUsac3aEijECz-dY79EmgkE1FP5cPKDsW1JKEceyBSTf5ES29BJD_xSeFNsyzJulgeMSVjCbjke_nNQENVy7MBDD-mwuYLlkqraCHGZkh1Oo1eXjuQkK3koa0So6EKZjlwH3WtZHuVGX9XAzsaNErvuuHRo9QelEMU7l5FMQd2dO93rPwyXPGl__2bKexc-3hvoaSs9Kz5uTp-Q30iuSXJdU2bGxqzbLzq_BQy1aag6nmNdCS3oaRWHL37rMT6fsu6K9ZHlQgcpNjujVwfkACKWiGIAWWVKZif3wx7Mppek2ApXWZKZr9A1ZtiwE7z9e7TRfq2U2X#m__cb1-3>{ <https://mail-attachment.googleusercontent.com/attachment/u/0/?ui=2&ik=aba66a32fc&attid=0.1&permmsgid=msg-f:1742328244751920533&th=182dfe4eae916d95&view=att&disp=inline&realattid=f_l7c1rr8i0&ser=1&saddbat=ANGjdJ_qVCrD5VtcwzbDcbDVeAnx9f6fofNi6MFWBJgCz-kQlYEx_Pci4UMbG80BfeZubUoYMz555AJPQ_GQrjr1ylClW6FqsctQ_q9XwxnECGc81qd5v9ZsHPBye9abZ-z7F7s332ZLrcB7CqT6cVZ1BQ9yCdbUq_emtRQoW08fcluey9zkq9TpCjACPnHj69Kj3ykd0TDz3R_IQSMVrbVu2zG1SqoLnMr0I5IpP_0zdYFUMc5KirVALGeMo2YEX88TwkuGnNreTra-tRooWHcf75Kyc4vKrW4Ym8y22tNpMsTABG7cL6eRiIwS03xUXiyTrUrbhv8rm42IQ22TU9ksCz8NqnLGMoiAdoeh1kxGPQtHPZM6QKWr-m19Gi-wZcnhpF-jiO6_U8t9meAQ6LxERVXj7oDZbSrEtH7C99YSbe_qBEWYCnIWFNMvd5LmsCagaWKn_QdXj_sp9i9sprmVhjRCWaW3uDgNYCE0dZnsLfec2uUAtbtytxYnk5oGjEXHtJuTyT7QUsac3aEijECz-dY79EmgkE1FP5cPKDsW1JKEceyBSTf5ES29BJD_xSeFNsyzJulgeMSVjCbjke_nNQENVy7MBDD-mwuYLlkqraCHGZkh1Oo1eXjuQkK3koa0So6EKZjlwH3WtZHuVGX9XAzsaNErvuuHRo9QelEMU7l5FMQd2dO93rPwyXPGl__2bKexc-3hvoaSs9Kz5uTp-Q30iuSXJdU2bGxqzbLzq_BQy1aag6nmNdCS3oaRWHL37rMT6fsu6K9ZHlQgcpNjujVwfkACKWiGIAWWVKZif3wx7Mppek2ApXWZKZr9A1ZtiwE7z9e7TRfq2U2X#m__cb1-4> using char_type = string::char_type; <https://mail-attachment.googleusercontent.com/attachment/u/0/?ui=2&ik=aba66a32fc&attid=0.1&permmsgid=msg-f:1742328244751920533&th=182dfe4eae916d95&view=att&disp=inline&realattid=f_l7c1rr8i0&ser=1&saddbat=ANGjdJ_qVCrD5VtcwzbDcbDVeAnx9f6fofNi6MFWBJgCz-kQlYEx_Pci4UMbG80BfeZubUoYMz555AJPQ_GQrjr1ylClW6FqsctQ_q9XwxnECGc81qd5v9ZsHPBye9abZ-z7F7s332ZLrcB7CqT6cVZ1BQ9yCdbUq_emtRQoW08fcluey9zkq9TpCjACPnHj69Kj3ykd0TDz3R_IQSMVrbVu2zG1SqoLnMr0I5IpP_0zdYFUMc5KirVALGeMo2YEX88TwkuGnNreTra-tRooWHcf75Kyc4vKrW4Ym8y22tNpMsTABG7cL6eRiIwS03xUXiyTrUrbhv8rm42IQ22TU9ksCz8NqnLGMoiAdoeh1kxGPQtHPZM6QKWr-m19Gi-wZcnhpF-jiO6_U8t9meAQ6LxERVXj7oDZbSrEtH7C99YSbe_qBEWYCnIWFNMvd5LmsCagaWKn_QdXj_sp9i9sprmVhjRCWaW3uDgNYCE0dZnsLfec2uUAtbtytxYnk5oGjEXHtJuTyT7QUsac3aEijECz-dY79EmgkE1FP5cPKDsW1JKEceyBSTf5ES29BJD_xSeFNsyzJulgeMSVjCbjke_nNQENVy7MBDD-mwuYLlkqraCHGZkh1Oo1eXjuQkK3koa0So6EKZjlwH3WtZHuVGX9XAzsaNErvuuHRo9QelEMU7l5FMQd2dO93rPwyXPGl__2bKexc-3hvoaSs9Kz5uTp-Q30iuSXJdU2bGxqzbLzq_BQy1aag6nmNdCS3oaRWHL37rMT6fsu6K9ZHlQgcpNjujVwfkACKWiGIAWWVKZif3wx7Mppek2ApXWZKZr9A1ZtiwE7z9e7TRfq2U2X#m__cb1-5> // ... <https://mail-attachment.googleusercontent.com/attachment/u/0/?ui=2&ik=aba66a32fc&attid=0.1&permmsgid=msg-f:1742328244751920533&th=182dfe4eae916d95&view=att&disp=inline&realattid=f_l7c1rr8i0&ser=1&saddbat=ANGjdJ_qVCrD5VtcwzbDcbDVeAnx9f6fofNi6MFWBJgCz-kQlYEx_Pci4UMbG80BfeZubUoYMz555AJPQ_GQrjr1ylClW6FqsctQ_q9XwxnECGc81qd5v9ZsHPBye9abZ-z7F7s332ZLrcB7CqT6cVZ1BQ9yCdbUq_emtRQoW08fcluey9zkq9TpCjACPnHj69Kj3ykd0TDz3R_IQSMVrbVu2zG1SqoLnMr0I5IpP_0zdYFUMc5KirVALGeMo2YEX88TwkuGnNreTra-tRooWHcf75Kyc4vKrW4Ym8y22tNpMsTABG7cL6eRiIwS03xUXiyTrUrbhv8rm42IQ22TU9ksCz8NqnLGMoiAdoeh1kxGPQtHPZM6QKWr-m19Gi-wZcnhpF-jiO6_U8t9meAQ6LxERVXj7oDZbSrEtH7C99YSbe_qBEWYCnIWFNMvd5LmsCagaWKn_QdXj_sp9i9sprmVhjRCWaW3uDgNYCE0dZnsLfec2uUAtbtytxYnk5oGjEXHtJuTyT7QUsac3aEijECz-dY79EmgkE1FP5cPKDsW1JKEceyBSTf5ES29BJD_xSeFNsyzJulgeMSVjCbjke_nNQENVy7MBDD-mwuYLlkqraCHGZkh1Oo1eXjuQkK3koa0So6EKZjlwH3WtZHuVGX9XAzsaNErvuuHRo9QelEMU7l5FMQd2dO93rPwyXPGl__2bKexc-3hvoaSs9Kz5uTp-Q30iuSXJdU2bGxqzbLzq_BQy1aag6nmNdCS3oaRWHL37rMT6fsu6K9ZHlQgcpNjujVwfkACKWiGIAWWVKZif3wx7Mppek2ApXWZKZr9A1ZtiwE7z9e7TRfq2U2X#m__cb1-6> if(s.starts_with("hello")) <https://mail-attachment.googleusercontent.com/attachment/u/0/?ui=2&ik=aba66a32fc&attid=0.1&permmsgid=msg-f:1742328244751920533&th=182dfe4eae916d95&view=att&disp=inline&realattid=f_l7c1rr8i0&ser=1&saddbat=ANGjdJ_qVCrD5VtcwzbDcbDVeAnx9f6fofNi6MFWBJgCz-kQlYEx_Pci4UMbG80BfeZubUoYMz555AJPQ_GQrjr1ylClW6FqsctQ_q9XwxnECGc81qd5v9ZsHPBye9abZ-z7F7s332ZLrcB7CqT6cVZ1BQ9yCdbUq_emtRQoW08fcluey9zkq9TpCjACPnHj69Kj3ykd0TDz3R_IQSMVrbVu2zG1SqoLnMr0I5IpP_0zdYFUMc5KirVALGeMo2YEX88TwkuGnNreTra-tRooWHcf75Kyc4vKrW4Ym8y22tNpMsTABG7cL6eRiIwS03xUXiyTrUrbhv8rm42IQ22TU9ksCz8NqnLGMoiAdoeh1kxGPQtHPZM6QKWr-m19Gi-wZcnhpF-jiO6_U8t9meAQ6LxERVXj7oDZbSrEtH7C99YSbe_qBEWYCnIWFNMvd5LmsCagaWKn_QdXj_sp9i9sprmVhjRCWaW3uDgNYCE0dZnsLfec2uUAtbtytxYnk5oGjEXHtJuTyT7QUsac3aEijECz-dY79EmgkE1FP5cPKDsW1JKEceyBSTf5ES29BJD_xSeFNsyzJulgeMSVjCbjke_nNQENVy7MBDD-mwuYLlkqraCHGZkh1Oo1eXjuQkK3koa0So6EKZjlwH3WtZHuVGX9XAzsaNErvuuHRo9QelEMU7l5FMQd2dO93rPwyXPGl__2bKexc-3hvoaSs9Kz5uTp-Q30iuSXJdU2bGxqzbLzq_BQy1aag6nmNdCS3oaRWHL37rMT6fsu6K9ZHlQgcpNjujVwfkACKWiGIAWWVKZif3wx7Mppek2ApXWZKZr9A1ZtiwE7z9e7TRfq2U2X#m__cb1-7> s.clear(); <https://mail-attachment.googleusercontent.com/attachment/u/0/?ui=2&ik=aba66a32fc&attid=0.1&permmsgid=msg-f:1742328244751920533&th=182dfe4eae916d95&view=att&disp=inline&realattid=f_l7c1rr8i0&ser=1&saddbat=ANGjdJ_qVCrD5VtcwzbDcbDVeAnx9f6fofNi6MFWBJgCz-kQlYEx_Pci4UMbG80BfeZubUoYMz555AJPQ_GQrjr1ylClW6FqsctQ_q9XwxnECGc81qd5v9ZsHPBye9abZ-z7F7s332ZLrcB7CqT6cVZ1BQ9yCdbUq_emtRQoW08fcluey9zkq9TpCjACPnHj69Kj3ykd0TDz3R_IQSMVrbVu2zG1SqoLnMr0I5IpP_0zdYFUMc5KirVALGeMo2YEX88TwkuGnNreTra-tRooWHcf75Kyc4vKrW4Ym8y22tNpMsTABG7cL6eRiIwS03xUXiyTrUrbhv8rm42IQ22TU9ksCz8NqnLGMoiAdoeh1kxGPQtHPZM6QKWr-m19Gi-wZcnhpF-jiO6_U8t9meAQ6LxERVXj7oDZbSrEtH7C99YSbe_qBEWYCnIWFNMvd5LmsCagaWKn_QdXj_sp9i9sprmVhjRCWaW3uDgNYCE0dZnsLfec2uUAtbtytxYnk5oGjEXHtJuTyT7QUsac3aEijECz-dY79EmgkE1FP5cPKDsW1JKEceyBSTf5ES29BJD_xSeFNsyzJulgeMSVjCbjke_nNQENVy7MBDD-mwuYLlkqraCHGZkh1Oo1eXjuQkK3koa0So6EKZjlwH3WtZHuVGX9XAzsaNErvuuHRo9QelEMU7l5FMQd2dO93rPwyXPGl__2bKexc-3hvoaSs9Kz5uTp-Q30iuSXJdU2bGxqzbLzq_BQy1aag6nmNdCS3oaRWHL37rMT6fsu6K9ZHlQgcpNjujVwfkACKWiGIAWWVKZif3wx7Mppek2ApXWZKZr9A1ZtiwE7z9e7TRfq2U2X#m__cb1-8> // ... <https://mail-attachment.googleusercontent.com/attachment/u/0/?ui=2&ik=aba66a32fc&attid=0.1&permmsgid=msg-f:1742328244751920533&th=182dfe4eae916d95&view=att&disp=inline&realattid=f_l7c1rr8i0&ser=1&saddbat=ANGjdJ_qVCrD5VtcwzbDcbDVeAnx9f6fofNi6MFWBJgCz-kQlYEx_Pci4UMbG80BfeZubUoYMz555AJPQ_GQrjr1ylClW6FqsctQ_q9XwxnECGc81qd5v9ZsHPBye9abZ-z7F7s332ZLrcB7CqT6cVZ1BQ9yCdbUq_emtRQoW08fcluey9zkq9TpCjACPnHj69Kj3ykd0TDz3R_IQSMVrbVu2zG1SqoLnMr0I5IpP_0zdYFUMc5KirVALGeMo2YEX88TwkuGnNreTra-tRooWHcf75Kyc4vKrW4Ym8y22tNpMsTABG7cL6eRiIwS03xUXiyTrUrbhv8rm42IQ22TU9ksCz8NqnLGMoiAdoeh1kxGPQtHPZM6QKWr-m19Gi-wZcnhpF-jiO6_U8t9meAQ6LxERVXj7oDZbSrEtH7C99YSbe_qBEWYCnIWFNMvd5LmsCagaWKn_QdXj_sp9i9sprmVhjRCWaW3uDgNYCE0dZnsLfec2uUAtbtytxYnk5oGjEXHtJuTyT7QUsac3aEijECz-dY79EmgkE1FP5cPKDsW1JKEceyBSTf5ES29BJD_xSeFNsyzJulgeMSVjCbjke_nNQENVy7MBDD-mwuYLlkqraCHGZkh1Oo1eXjuQkK3koa0So6EKZjlwH3WtZHuVGX9XAzsaNErvuuHRo9QelEMU7l5FMQd2dO93rPwyXPGl__2bKexc-3hvoaSs9Kz5uTp-Q30iuSXJdU2bGxqzbLzq_BQy1aag6nmNdCS3oaRWHL37rMT6fsu6K9ZHlQgcpNjujVwfkACKWiGIAWWVKZif3wx7Mppek2ApXWZKZr9A1ZtiwE7z9e7TRfq2U2X#m__cb1-9>}
>
> I don't think that code is ordinary "just programming" at all!
> `std::string::char_type` (1) does not exist, and (2) even if it did exist,
> I assume it would be an unnecessarily verbose way of spelling "char". So
> let's eliminate that line. Then, we're left with nicely* generic *code,
> that looks just like classic Stepanov STL code. This function template (or
> "algorithm") can be compiled and works perfectly for any concrete type that
> implements the `starts_with` method (e.g. `string`, `string_view`) and the
> `clear` method (e.g. `string`, `vector`, `deque`, `map`, `set`...)
>
> template<class T>
> void silly(T& t) {
> if (t.starts_with("hello")) t.clear();
> }
>
> Of course in the actual STL there's only the one type (`string`) that
> supports both of those operations. But that's fine, because that's the only
> STL type that can actually be used with this template. If we intended to
> use it with both `string` and `string_view`, we could generalize it a
> little further like this:
>
> template<class T>
> void silly(T& t) {
> if (t.starts_with("hello")) t = T();
> }
>
> But nobody writes templates in a vacuum: there's always some actual
> business purpose behind writing the template. Usually it's to avoid code
> duplication: we have two or more *known* types that satisfy the same
> interface, and so we can write one ("statically polymorphic") version of
> our algorithm using a template like `silly`. The interface and the template
> algorithm generally will evolve cooperatively. For example, the STL is
> designed to facilitate the writing of algorithms that work for any kind of
> STL container, so, all STL containers support the same vocabulary of
> methods: `insert`, `erase`, `begin`, `end`, `T::iterator`, `T::value_type`,
> and so on.
>

I think I will change the example to not be a string or have standard
operations. This was supposed to be some simple user code, a user class of
whatever.


>
> It seems to me that you're identifying the problem as "I can't write a
> template that works for *all possible types*, because
> (statically-)polymorphic code implies an interface, and not every possible
> type will implement the interface I require."
>
But that's not a real-world problem, because in the real world we don't
> write code to work with *every possible type*.
>
And then, you have an XY problem: you try to get around this artificial
> problem by crufting up your code, turning all your methods into free
> functions and adding a lot of `::`s, and then complain that this makes the
> code uglier. Yes — but that's the "Y" problem! Crufting up the code is
> ugly, but it isn't necessary to solve your "X" problem; and in fact, it's
> not even *sufficient*. In order to use polymorphism (*either* static
> polymorphism with templates, *or* classical runtime polymorphism with
> inheritance), your types must conform to some kind of interface. That's
> both unavoidable and beneficial-to-the-reader.
>

This is not fair. The problem is that we have *two* static polymorphisms
right now:
 - One is the naive-but-simple "turn it into tparam"
This one considers the interface as something natural to the type - a type
having begin(), contains() is a container. Period. Conforming to that
interface is "hard" - it *has to* come naturally, effectively be
subclassing.
 - One is (very) advanced
This one, on the contrary, does not assume the type models the interface -
it might, it might not, in any case the type must be able to model it...
any type. Also, exactly because there are no assumptions, the interface
needs nominal conformance. Conforming is "easy" in the sense it does not
require subclassing. *However* all the burden is on the original developer
of the genetic code. Not only a heavy burden, but code change requirement
as well, a rewrite if not planned for.

Are we OK with that? Is this a natural separation or a language limitation?
Or may be a natural evolution that highlights a limitation?
Is the solution polishing the second and still having two systems, or
overhauling the first to the point it can serve the second as well?


>
> my $.02,
> Arthur
>

Received on 2022-08-30 15:51:50