libfn / functional

Extending C++ library for functional programming
ISC License
60 stars 8 forks source link

C++20 support #86

Open nilssonk opened 1 month ago

nilssonk commented 1 month ago

Hello there,

I just now saw your impressive presentation from cppnow earlier this year and would like to use this in production at my current company. However the C++23 requirement is a big ask for us seeing as we are still only in the very early evaluation stage for C++20 (which itself may be considered early adoption in much the embedded space). So my question is, what C++23 features are actually required for this to work (modulo replacable stdlib components such as expected and optional)? If there are none, maybe we could collaborate on making a C++20 version?

I naively tried a string replace 23->20 in the CMakeLists.txt, but the build chokes on constexpr usage of std::string_view(data, size) and many many lines of other perhaps unrelated stuff, so I thought I'd ask first before putting in more effort.

Many thanks for sharing the project, Kim

Bronek commented 1 week ago

Hi. The problem with C++20 support is that it does not support #include <expected> which we rely on, as a part of the implementation of fn::expected; however there might be a suitable polyfill and also a similar use case which we would like to support, which is clang with -stdlib=libstdc++. So, I am not saying "no" but am also not promising anything. It is a nontrivial amount of work.

Also, this library needs sorting of types which is currently a poor-man emulation in the form of a constexpr algorithm inside functional/detail/meta.hpp, which only handles named types, and not even very well. Sorting of types is a proposed for C++26 P2830 and once it is available, we will likely remove this poor-man emulation and this library will only support C++26. So, assuming that we actually do add support (again, no promises) for C++20, it will be only temporary for few years, and then removed.

atomgalaxy commented 1 week ago

We realistically should support an opt-in adaptor where you can plug in your monad types. That's the path to C++20.

nilssonk commented 5 days ago

I sat down with this for an hour or two and here's what I've done:

  1. Introduced a CPP20_COMPAT option to the project which controls the version of CMAKE_CXX_STANDARD and optionally downloads drop-in libraries.
  2. Added a candidate drop-in for expected in the form of https://github.com/TartanLlama/expected .
  3. Added a candidate drop-in for string_view with support for the constexpr version of the constructor basic_string(char*, size_t) in the form of https://github.com/martinmoene/string-view-lite
  4. Introduced a header with compatibility type aliases for the internal expected and related types (e.g. unexpected, in_place).
  5. Introduced a header with compatibility type aliases for the internal string_view.
  6. Replaced many std:: with detail:: .
  7. Worked around _normalized_name::apply() usage of constexpr std::string::append() by having it return a fixed size array together with a size value.
  8. Replaced usage of std::unreachable with the cppreference.com implementation.
  9. Removed static keywords from constexpr lambdas and various operator()s (this seems unsound).
  10. Replaced std::invoke_r with std::__invoke_r.

However now I'm sort of stuck and I think the issue is that the standard library uses a shared type std::in_place for both optional and expected, while my drop in uses its own tl::in_place, thereby creating a schism. It may be possible to work around this by using another drop-in for std::optional (e.g. https://github.com/TartanLlama/optional) and making sure that their notions of in_place are the same. However this whole porting business is getting more dubious by the minute.

Do you think 9 would be a show stopper and do you foresee any other boobytraps?

atomgalaxy commented 5 days ago

9 is not that crucial. You just get a worse calling convention.

3: string_view is an implementation convenience, I think it's only really

needed for type sorting, and we can reimplement that with C arrays and memcmp. IMO a better way is to just rip it out.

6: not really sure what that does, I'd have to review that.

10 scares me, I hope you did that via some kind of macro...

All the above is because I'd prefer us to have a proper subset of the library supported in C++20, and not some bastardized shimmed version.

On Tue, Oct 15, 2024 at 10:06 PM Kim Nilsson @.***> wrote:

I sat down with this for an hour or two and here's what I've done:

  1. Introduced a CPP20_COMPAT option to the project which controls the version of CMAKE_CXX_STANDARD and optionally downloads drop-in libraries.
  2. Added a candidate drop-in for expected in the form of https://github.com/TartanLlama/expected .
  3. Added a candidate drop-in for string_view with support for the constexpr version of the constructor basic_string(char*, size_t) in the form of https://github.com/martinmoene/string-view-lite
  4. Introduced a header with compatibility type aliases for the internal expected and related types (e.g. unexpected, in_place).
  5. Introduced a header with compatibility type aliases for the internal string_view.
  6. Replaced many std:: with detail:: .
  7. Worked around _normalized_name::apply() usage of constexpr std::string::append() by having it return a fixed size array together with a size value.
  8. Replaced usage of std::unreachable with the cppreference.com implementation.
  9. Removed static keywords from lambdas and operator()s (this seems unsound).
  10. Replaced std::invoke_r with std::__invoke_r.

However now I'm sort of stuck and I think the issue is that the standard library uses a shared type std::in_place for both optional and expected, while my drop in uses its own tl::in_place, thereby creating a schism. It may be possible to work around this by using another drop-in for std::optional (e.g. https://github.com/TartanLlama/optional) and making sure that their notions of in_place are the same. However this whole porting business is getting more dubious by the minute.

Do you think 9 would be a show stopper and do you foresee any other boobytraps?

— Reply to this email directly, view it on GitHub https://github.com/libfn/functional/issues/86#issuecomment-2415157782, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAA5R5O3SC37BDBY5EU3HQLZ3V7V3AVCNFSM6AAAAABOHXDDW6VHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDIMJVGE2TONZYGI . You are receiving this because you commented.Message ID: @.***>

Bronek commented 4 days ago

Note this library is still in a dynamic development stage, e.g. I plan to move the multi-dispatch implementation away from fn::invoke to fn::dispatch (or perhaps fn::apply) #84 , rename fn::sum to fn::copack #83, improve graded monad support #98 and quite possibly other high-churn changes. This means your work on C++20 compatibility will quickly become obsolete/conflict with the state of the world.

Bronek commented 4 days ago

I think the approach which will work well is to make separate changes in this library which, when taken individually, will not make it outright compatible with C++20, but will bring it closer by removing individual barriers.