seqan / seqan3

The modern C++ library for sequence analysis. Contains version 3 of the library and API docs.
https://www.seqan.de
Other
405 stars 81 forks source link

create `std` module #239

Closed h-2 closed 5 years ago

h-2 commented 6 years ago

We will create a module called std that contains all wrapper and aliases of std and expected std functionality, i.e. implementations of standard library concepts and type_traits, as well as aliases for range-v3 functionality that is expected to be merged into the standard.

Reason: this signals clearly to developers that something called foo and defined in that module is identical to such foo in the standard library. It is also an indicator of "all this stuff is not biological, just infrastructure" and it also makes it easier to identify and remove the code in the distant future.

Checklist

In general I would propose:

marehr commented 6 years ago

Do you mean by

move most of core/metafunction to std/type_traits

the same as in #243?

h-2 commented 5 years ago

This is the link to the current Ranges proposal: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p0789r3.pdf

You can look up there whether something will (likely) be included or not.

h-2 commented 5 years ago

@smehringer @joshuak94

I will try to explain this issue in more detail:

Currently we rely heavily on the range-v3 library for providing lots of functionality. Most of the functionality will be part of C++20, but quite a few things will not, and some of the things will be, but under different names. To avoid code-duplication and similar-but-different function names et cetera we decided to rely only on those parts of range-v3 that will be part of C++20. Furthermore we would like to only have to depend on the range-v3 library if we cannot actually use C++20. This also means we need to find out which things won't be part of C++20 and implement those ourselves anyway (I call this CATEGORY0 for now).

To do this we decided to create an abstraction layer in the form of the std module which redirects to either the actual standard library (if C++20) or to the range-v3 library otherwise. We further decided to make this abstraction layer appear just like the standard library to make transition later on transparent and make the code easier to read (i.e. not a new namespace, but inside std::). This is easy to do for things that are new (CATEGORY1a), because there are no conflicts between the names we introduce and those already present in the standard library (one example is std/concepts); but it is still not perfect:

Anyway, it gets more difficult for things that have changed in C++20 (CATEGORY1b), because we need to make our implementations preferred to those already in the standard. For plain functions and types it is impossible, but lucky for us, most of the things are templates and most templates in the current standard library are unconstrained so we can add bogus constraints that make the compiler pick our implementations, because they appear more specialised. For function templates this works well, but for type templates it is more difficult, we have to add wrapper templates, like discussed above and make those a specialisation of the original.

h-2 commented 5 years ago

So much for the general reasoning. As for why the range-v3 library and C++ have new versions of begin(), end(), swap()...: The problem with all of these in the current standard is that they don't handle argument-dependent-lookup(ADL) well. ADL is controversial and nobody likes it, but there is no getting rid of it any time soon.

Let's illustrate this with an example. std::begin() calls the .begin() member function if possible and it also works for regular arrays. You can also overload the std::begin() free function for your type, if you don't provide the member, but you might not want to that, because you are already providing that in your own namespace and if you declare both they will clash if someone does using namespace on, both, your namespace and std. ¹ If you only declare in your own namespace std::begin() will not pick it up. This is the same way, you can currently not overload std::swap in you own namespace. So what smart programmers do is the following:

using std::begin;
auto it = begin(s);

This tells the compiler to look for begin() in the current namespace, in the namespaces associated with the argument (ADL) and in namespace std. But it is absurdly complex and no regular programmer understands this. That's why we have ranges::begin() and in the future std::ranges::begin(), it does all those things for you and in the right order. I had hoped they would just replace the existing std::begin(), but since the behaviour is slightly different in some cases, and most importantly std::begin() is a function and std::ranges::begin() is a functor it would have been a breaking change so now we have two of them.

¹ We are seeing exactly this for seqan3::pod_tuple which has get overloads in seqan3:: and std::.

marehr commented 5 years ago

@h-2 Can you update the checkboxes? I think move most of core/metafunction to std/type_traits is done, right?

h-2 commented 5 years ago

move to individual issues