Can you write a concept for ContiguousIterator? - c++

I know there is concept for ContiguousIterator in words specification sense, but I wonder if it can be written using C++20/C++17 Concepts TS syntax.
My problem with this is that unlike RandomAccessIterator ContiguousIterator requires not just some operations like it+123 to work, but depends on runtime result of that operation.

No you cannot, not without a traits class or other helper, where types opt-in to being contiguous.

Your problem is currently unsolvable. The committee is considering what to do about deducing contiguous memory access. The flub is that iterator_category is not a trait (although it resides in iterator_traits); It is an ad-hoc type. It cannot be subtyped without breaking existing code. (Beginner mistake, eh what?) The Committee has recognized the mess. This recent discussion tells all -> How to deduce contiguous memory from iterator

Related

Why are only these C++ standard library containers guaranteed to allow incomplete types?

It's a well-known fact that the C++ standard library containers, in general, cannot be instantiated with incomplete types. The result of doing so is UB, although in practice a given implementation will either accept the code without issues or issue a compilation error. Discussion about this restriction can be found here: Why C++ containers don't allow incomplete types?
However, in C++17, there are three containers that explicitly allow incomplete types: std::forward_list (26.3.9.1/4), std::list (26.3.10.1/4), and std::vector (26.3.11.1/4).
This is the result of N4510. The paper notes that "based on the discussion on the Issaquah meeting" the decision was made to, at least at first, limit such support to those three containers. But why?
Because we know how to implement those containers to deal with incomplete types, without breaking the ABI.
std::array, on the other hand, needs to know how big an element is (for example).
But why?
The reason incomplete types weren't allowed in the standard containers was that some containers can work with them, but some don't. They didn't want to think too much about this issue at the time and made a blanket prohibition of incomplete types in all standard containers.
Matt Austern documented that in his great article "The Standard Librarian: Containers of Incomplete Types", which is no longer available, but there are still quotes from it in Boost Containers of Incomplete Types.
This C++17 change does justice by undoing the harm inflicted by that blanket prohibition.

New iterator requirements

I noticed that most if not all containers now require their ::iterator type to satisfy LegacySomethingIterator instead of SomethingIterator.
For example, std::vector<>::iterator now requires:
iterator LegacyRandomAccessIterator
This seems to be the same for most of the other containers, all requiring their iterators to go from SomethingIterator to LegacySomethingIterator.
There are also the "new" requirements that took the names of the old requirements, such as RandomAccessIterator, why were these added? It seems to me that the new variants just shadow the legacy variants, no differences.
Why were new ones created in the first place, their requirements look the same to me. Why don't the new ones just replace the old requirements instead of right now having 2 different names for them (e.g. RandomAccessIterator and LegacyRandomAccessIterator)?
These are not new things, hence the term "legacy". This is simply how the cppreference site chooses to reconcile the fact that C++20 will have two different things that are both "concepts" called "RandomAccessIterator" (well, until C++20 decided to rename their version random_access_iterator).
Pre-C++20, a "concept" was just a set of requirements in the standard that represented the behavior expected of certain template parameters. In C++20, with concepts becoming an actual language feature, that needed to shift. The problem is that the Ranges concept of "RandomAccessIterator" is not the same as the old-style "concept" of "RandomAccessIterator".
Since C++ considers them both to be "concepts" (though only the newer one is a concept in the language sense), they would both have the same page name on the Wiki. And MediaWiki doesn't really allow that.
So the maintainers of the site settled on using "Legacy" to differentiate them. Note that the actual standard doesn't use this "Legacy" prefix.
Note that the C++20 standard does have a prefix for the older concepts: "Cpp17". So the old concept would be "Cpp17RandomAccessIterator". That was not deemed appropriate for Cppreference for obvious reasons.

Is there anything else to std::cbegin() other than begin()ing a const reference?

I'm constrained to writing C++11 code, but I want to use std::cbegin(). So, I'm looking at GCC 5.4.0's implementation, in /usr/include/c++/5/bits/range_access.h on my system, thinking I might write something similar, and I see:
template<class _Container>
inline constexpr auto
cbegin(const _Container& __cont) noexcept(noexcept(std::begin(__cont)))
-> decltype(std::begin(__cont))
{ return std::begin(__cont); }
is that all there is to it? Am I missing something? If that's it, how come it wasn't part of C++11 like std::begin()?
is that all there is to it?
Yes.
Am I missing something?
Not that I'm aware of.
If that's it, how come it wasn't part of C++11 like std::begin()?
The global templates seem to have been part of the original proposal as an alternative to the member functions, but the proposal preferred to only provide the member functions in favour of providing either just the global templates, or both the templates and members. (Assuming this is the original proposal: N1674).
The committee chose to include the member function alternative in C++11, and the template not until C++14. I'm not part of the committee, and cannot speak for them, but my guess is that the attitude of the proposal may have affected the decision:
While this generic adapter alternative seems quite straightforward, we nonetheless favor the
member function approach as proposed above. It seems more in keeping with current C++
programming idioms, such as the parallel use of
rbegin
as a container member function rather
than as a generic adapter
Here is the development for the C++ Standard Library Defect Report issue (2128) where the template versions were decided to be adopted into C++14 after all.
No, that covers it.
Although a small function can be added to the standard with a relatively small amount of effort, time is finite and the committee doesn't have unlimited resource. Another example of a reasonably useful and trivial function that was omitted until C++14 is std::make_unique. Things improve over time.

Restricting std::sort to random access iterators

I was just wondering, since you can only pass random access iterators to std::sort anyway, why not enforce that restriction by defining it only for random access iterators in the first place?
#include <iterator>
#include <type_traits>
template <typename ForwardIterator>
typename std::enable_if<
std::is_same<
typename std::iterator_traits<ForwardIterator>::iterator_category,
std::random_access_iterator_tag>::value,
void>
::type sort(ForwardIterator begin, ForwardIterator end)
{
// ...
}
I find a single line error message a lot easier to read than pages and pages of error messages resulting from type errors far down in the implementation.
You could do the same with other algorithms. The standard C++ core language has always been expressive enough for that task, right? So, any particular reason why this was not done?
The core language has always been expressive enough to handle such checks, but when the first standard was being prepared (around 1996/1997), the tricks that you can play with SFINAE (what enable_if is based upon) were not yet known and the support for advanced template wizardry was limited in the compilers.
So, the reason why the standard did not mandate it was because the needed techniques were not invented yet.
The reason why compiler/library writers did not add it after the fact is probably just plain economics: not enough people asked for the feature, and when people did start asking for better diagnostics, hope was on the concepts proposal to take care of it. Unfortunately, this proved to be a bit too hard to get finalised in time.
My guess is that SFINAE was invented (or discovered) after the standard library implementations had reached a certain maturity. After that, changes to the core library had to be very justified in order to prevent the introduction of regressions and I guess that mere cosmetics are somewhat hard to justify.
That said, the GCC for example already does have a lot of diagnostics for template-related error messages, e.g. macros that perform a kind of concept checking. For example, the GCC-libstdc++ has the following:
// concept requirements
__glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept<
_RandomAccessIterator>)
__glibcxx_function_requires(_LessThanComparableConcept<_ValueType>)
__glibcxx_requires_valid_range(__first, __last);
Actually, when there is only one overload of an algorithm, you'll nearly always get better diagnostics by causing a compilation error just inside using something like Boost.ConceptCheck or __glibcxx_function_requires. When SFINAE (which is what enable_if uses) leaves you with an empty overload set, most compilers simply tell you "there's no matching function," which tends not to be very helpful.
One of the nice things about templates in C++ is they can have a sort of static 'duck typing'. I can't speak for this particular case, but in many templates, as long as you keep the interface the same, all the hierarchy nonsense doesn't matter. And that's a good thing.

Inheriting from iterator [duplicate]

Can/Should i inherit from STL iterator to implement my own iterator class? If no, why not?
Short answer
Many consider that the class std::iterator does not offer much compared to regular type aliases, and even obfuscates them a bit by not explicitly providing the names and relying on the order of the template parameters instead. It is deprecated in C++17 and is likely to be gone in a few years.
This means that you shouldn't use std::iterator anymore. You can read the whole post below if you're interested in the full story (there's a bit of redundancy since it has been started before the deprecation proposal).
Legacy answer
You can ignore everything below if you're not interested in history. The following fragments even contradict themselves several times.
As of today (C++11/C++14), the standard seems to imply that it isn't a good idea anymore to inherit from std::iterator to implement custom iterators. Here is a brief explanation, from N3931:
Although the Standard has made this mistake almost a dozen times, I recommend not depicting directory_iterator and recursive_directory_iterator as deriving from std::iterator, since that's a binding requirement on implementations. Instead they should be depicted as having the appropriate typedefs, and leave it up to implementers to decide how to provide them. (The difference is observable to users with is_base_of, not that they should be asking that question.)
[2014-02-08 Daniel comments and provides wording]
This issue is basically similar to the kind of solution that had been used to remove the requirement to derive from unary_function and friends as described by N3198 and I'm strongly in favour to follow that spirit here as well. I'd like to add that basically all "newer" iterator types (such as the regex related iterator) don't derive from std::iterator either.
The paper cites N3198 which itself states that it follows the deprecation discussed in N3145. The reasons for deprecating the classes that only exist to provide typedefs are given as such:
Our experience with concepts gives us confidence that it is rarely necessary to depend on specific base class-derived class relations, if availability of types and functions is sufficient. The new language tools allow us even in the absence of language-supported concepts to deduce the existence of typenames in class types, which would introduce a much weaker coupling among them. Another advantage of replacing inheritance by associated types is the fact, that this will reduce the number of cases, where ambiguities arise: This can easily happen, if a type would inherit both from unary_function and binary_function (This makes sense, if a functor is both an unary and a binary function object).
tl;dr: classes which only provide typedefs are now deemed useless. Moreover, they increase coupling when it is not needed, are more verbose, and can have unwanted side effects in some corner cases (see the previous quotation).
Update: issue 2438 from N4245 seems to actually contradict what I asserted earlier:
For LWG convenience, nine STL iterators are depicted as deriving from std::iterator to get their iterator_category/etc. typedefs. Unfortunately (and unintentionally), this also mandates the inheritance, which is observable (not just through is_base_of, but also overload resolution). This is unfortunate because it confuses users, who can be misled into thinking that their own iterators must derive from std::iterator, or that overloading functions to take std::iterator is somehow meaningful. This is also unintentional because the STL's most important iterators, the container iterators, aren't required to derive from std::iterator. (Some are even allowed to be raw pointers.) Finally, this unnecessarily constrains implementers, who may not want to derive from std::iterator. (For example, to simplify debugger views.)
To sum up, I was wrong, #aschepler was right: it can be used, but it is certainely not required - it isn't discouraged either. The whole "let's remove std::iterator" thing exists for the standard not to constrain the standard library implementers.
Round 3: P0174R0 proposes to deprecate std::iterator for a possible removal in the future. The proposal is already pretty good at explaining why it should be deprecated, so here we go:
The long sequence of void arguments is much less clear to the reader than simply providing the expected typedefs in the class definition itself, which is the approach taken by the current working draft, following the pattern set in C++14 where we deprecated the derivation throughout the library of functors from unary_function and binary_function.
In addition to the reduced clarity, the iterator template also lays a trap for the unwary, as in typical usage it will be a dependent base class, which means it will not be looking into during name lookup from within the class or its member functions. This leads to surprised users trying to understand why the following simple usage does not work:
#include <iterator>
template <typename T>
struct MyIterator : std::iterator<std::random_access_iterator_tag, T> {
value_type data; // Error: value_type is not found by name lookup
// ... implementations details elided ...
};
The reason of clarity alone was sufficient to persuade the LWG to update the standard library specification to no longer mandate the standard iterator adapators as deriving from std::iterator, so there is no further use of this template within the standard itself. Therefore, it looks like a strong candidate for deprecation.
This is becoming a bit tiring and not everyone seems to agree, so I will let you draw your own conclusions. If the committee eventually decides that std::iterator should be deprecated, then it will make it pretty clear that you shouldn't use it anymore. Note that the follow-up paper highlights a great support for the removal of std::iterator:
Update from Jacksonville, 2016:
Poll: Deprecate iterator for C++17??
SF  F   N   A   SA
6    10  1    0   0
In the above poll results, SF, F, N, A and SA stand for Strongly For, For, Neutral, Against and Strongly Against.
Update from Oulu, 2016:
Poll: Still want to deprecate std::iterator?
SF F N A SA
3   6  3  2  0
P0619R1 proposes to remove std::iterator, possibly as soon as C++20, and also proposes to enhance std::iterator_traits so that it can automatically deduce the types difference_type, pointer and reference the way std::iterator does when they're not explicitly provided.
If you mean std::iterator: yes, that's what it's for.
If you mean anything else: no, because none of the STL iterators have virtual destructors. They're not meant for inheritance and a class inheriting from them might not clean up properly.
No one should not because of the potential problems that might be encountered. Probably you are better off using Composition rather than Inheritance with STL Iterators.
Undefined Behavior due to absence of virtual destructors:
STL containers & iterators are not meant to act as base classes as they do not have virtual destructors.
For classes with no virtual destructors being used as Base class, the problem arises when deallocating through a pointer to the base class (delete, delete[] etc). Since the classes don't have virtual destructors, they cannot be cleaned up properly and results in Undefined Behavior.
One might argue that there would not be a need to delete the iterator polymorphically & hence nothing wrong to go ahead with deriving from STL iterators, well there might be some other problems like:
Inheritance maynot be possible at all:
All iterator types in the standard container are Implementation defined.
For e.g: std::vector<T>::iterator might be just a T*. In this case, you simply cannot inherit from it.
The C++ standard has no provisions demanding that say std::vector<T>::iterator does not
use inheritance inhibiting techniques to prevent derivation. Thus, if you are deriving from a STL iterator you are relying on a feature of your STL that happens to allow derivation. That makes such an implementation non portable.
Buggy behaviors if not implemented properly:
Consider that you are deriving from vector iterator class like:
class yourIterator : std::vector<T>::iterator { ... };
There might be a function which operates on the vector iterators,
For ex:
void doSomething(std::vector<T>::iterator to, std::vector<T>::iterator from);
Since yourIterator is a std::vector<T>::iterator you can call doSomething() on your container class but you will be facing the ugly problem of Object Slicing. The doSomething() has to be implemented in a proper templated manner, to avoid the
problem.
Problems while using Standard Library Algorithms:
Consider you are using the derivation from vector iterator, and then you use a Standard library algorithm like std::transform()
For Ex:
yourIterator a;
yourIterator b;
...
std::transform( a++, b--, ... );
The postfix operator ++ returns a std::vector<T>::iterator and not a
yourIterator resulting in a wrong template being chosen.
Thus, Inheriting from STL Iterators is possible indeed but if you ready to dig out all such and many other potential problems and address them, Personally I won't give it the time and the effort to do so.
If you're talking about std::iterator template, then yes, you should, but I hope you do understand that it has no functionality, just a bunch of typedefs. The pro of this decision is that your iterator can be fed to iterator_traits template.
If, on the other hand, you're talking about some specific STL iterator, like vector<T>::iterator or other, then the answer is a resounding NO. Let alone everything else, you don't know for sure that it's actually a class (e.g. the same vector<T>::iterator can be just typedefed as T*)