Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

create std module #239

Closed
3 of 8 tasks
h-2 opened this issue Apr 25, 2018 · 6 comments
Closed
3 of 8 tasks

create std module #239

h-2 opened this issue Apr 25, 2018 · 6 comments
Assignees

Comments

@h-2
Copy link
Member

h-2 commented Apr 25, 2018

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

  • create module and at least basic documentation
  • move most of core/concept there
  • update concepts to be interfaces, add interface documentation
    • most things, but not all
  • move most of core/metafunction to std/type_traits
  • add aliases for <algorithm> from range-v3
  • add aliases for free frunctions for ranges from range-v3 (begin(), end(), size(), ...)
  • add aliases for view from range-v3

In general I would propose:

  • All usage of ranges:: content must go through aliases in the std module.
  • Any of the things in std that will likely not land in c++20 should be reimplemented in our library (and moved out of std again)
  • this way we can ensure that SeqAn3 in combination with C++20 works without the ranges library.
@h-2 h-2 added this to the Feature Pre-release (June) milestone Apr 25, 2018
@h-2 h-2 self-assigned this May 30, 2018
@marehr
Copy link
Member

marehr commented Jun 6, 2018

Do you mean by

move most of core/metafunction to std/type_traits

the same as in #243?

@h-2 h-2 mentioned this issue Jul 4, 2018
@h-2
Copy link
Member Author

h-2 commented Oct 15, 2018

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
Copy link
Member Author

h-2 commented Oct 17, 2018

@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:

  • To import objects, we can use using ::ranges::object_name, e.g. for ranges::begin() which is implemented as a functor.
  • To import functions or function templates, we can wrap them.
  • To import types we can use using, but for type templates we loose type deduction guides, because they just don't work on typedefs. An alternative is to declare a "wrapper-type" like with the function, but then we need to add all sorts of cruft, because templates inheriting other templates don't inherit constructors and member types.

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
Copy link
Member Author

h-2 commented Oct 17, 2018

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
Copy link
Member

marehr commented Nov 6, 2018

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

@rrahn rrahn added the Epic label Nov 20, 2018
@h-2 h-2 removed this from the June Sprint / Feature Pre-release milestone Nov 26, 2018
@h-2
Copy link
Member Author

h-2 commented Nov 26, 2018

move to individual issues

@h-2 h-2 closed this as completed Nov 26, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants