Closed h-2 closed 5 years ago
Do you mean by
move most of
core/metafunction
tostd/type_traits
the same as in #243?
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.
@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:
using ::ranges::object_name
, e.g. for ranges::begin() which is implemented as a functor.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.
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::
.
@h-2 Can you update the checkboxes? I think move most of core/metafunction to std/type_traits
is done, right?
move to individual issues
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 suchfoo
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
core/concept
therecore/metafunction
tostd/type_traits
<algorithm>
from range-v3In general I would propose:
ranges::
content must go through aliases in the std module.