std::back_insert_iterator in C++17 - c++

As shown here std::back_insert_iterator in pre- C++17 inherits from std::iterator while it doesn't in C++17. What is the reason for this change?

std::iterator is a convenience. It provides a handful of typedefs that code that uses iterators find useful. The preferred mechanism these days is std::iterator_traits, which is more flexible.
When an iterator is, in fact, a pointer it can't inherit from std::iterator, so iterator_traits has always been the way to get those typedefs. Having the typedefs in iterator types that are classes but not in iterator types that are pointers means that generic code can't use those members. Having them is minimally useful, and they're going away.

Related

Should we still use classes or functions that require std::iterator if std::iterator is deprecated? [duplicate]

This question already has answers here:
Why is std::iterator deprecated?
(2 answers)
Closed 2 years ago.
I heard std::iterator is deprecated in C++17.
For example, like functions from <algorithm>, more likely we're going to be using begin() and end() member functions of objects which return iterator, like std::string, std::vector, etc.
Or like range-based for loops, where we will need begin() and end() which return iterator as well.
So therefore, if std::iterator as the base class is deprecated, should we even use member functions like begin() and end() or use other functions in the STL that require an iterator?
For example, like functions from <algorithm>
None of the functions from <algorithm> require std::iterator. It's fine to use them despite the deprecation of std::iterator.
more likely we're going to be using begin() and end() member functions
None of those require the use of std::iterator.
which return iterator as well.
Iterators are not deprecated. The class template std::iterator is deprecated.
should we even use member functions like begin() and end() or use other functions in the STL that require an iterator?
Yes. Although, I would recommend using them through std::ranges when convenient (in C++20).
So iterators inside of object/class like std::vector<int>::iterator are not inherited from std::iterator?
Standard library iterator types are defined by the standard library implementation. Technically, they could inherit from std::iterator but they are not required nor guaranteed to be inherited from it. Whether they inherit from std::iterator or not, they are not themselves deprecated.
std::iterator used to be intended to be used as a base class for custom iterators. Unless you are defining a custom iterator, you would not have been using it in the first place. If you are defining a custom iterator, you should not use std::iterator anymore. Note that it was never necessary to use std::iterator for this purpose.
The deprecation of std::iterator is purely deprecating it use as a base class.
Using begin() and end() and iterators in general isn't affected by this at all.
Basically, all this is saying is that when you define an iterator, you should have something like:
template <class T /* ... */>
class my_iterator {
// the following names are what `std::iterator` defines for you:
using iterator_category = std::forward_iterator_tag;
using value_type = T;
using reference = T&;
using pointer = T*;
using difference_type = std::ptrdiff_t;
// ...
};
...and not:
template <class T /* .. */>
class my_iterator : public std::iterator<std::forward_iterator_tag, T> {
// ...
};
It also means the iterators in the standard library are intended to be done pretty much the same way (which they mostly have been, but depending on how you read it, there's an argument that older versions of the standard at least implied that they should be implemented by inheriting from std::iterator as well).
Since you mention begin() and end(), I suppose it's worth adding an unrelated point: it is generally better to use std::begin() and std::end() rather than the member functions of various collection classes. By doing this, your code can then work with built-in arrays, rather than just classes that define begin() and end() as member functions. But this is entirely unrelated to std::iterator being deprecated.
std::iterator is an iterator building block. It's not a valid iterator, and definitely not the iterator. The concept of iterators is by no means abandoned. There are no "classes or functions" in the C++ library that require std::iterator. None. There are classes and functions that use iterators in general, as a concept, but that has nothing whatsoever to do with std::iterator.
You have probably never used std::iterator anyway, since its only use from a user perspective is to implement custom iterators... So you'd have only used it knowingly if you implemented custom iterators and chose to derive them from std::iterator. The standard library was free to use std::iterator as it saw fit, but this was in implementation detail and there was no expectation in the C++ standard that any of the various iterators offered by the C++ library would actually use std::iterator.

Canonical way to define forward output iterator

How does one define forward-output-iterators in C++11 in a canonical way?
According to the standard a forward_iterator is only a input_iterator. So the corresponding forward_iterator_tag only extends input_iterator_tag. If we are using std::iterator to define our iterators, what tag do we use for a forward-output-iterator?
Is it canonical to define a private tag that extends both forward_iterator_tag and output_iterator_tag or is there a better solution?
The canonical thing to do is to inherit from std::iterator<std::forward_iterator_tag, T> only. Iterators have only one category.
The standard has no algorithms (or other uses) for an output iterator that is also a forward iterator. All uses of output iterators in the standard require only single-pass.
Instead, the standard has the idea of mutable vs. immutable iterators of categories forward/bidi/randomaccess. All the algorithms that need to write through iterators, and that require better than single-pass, also read through the same iterators they write through. This is std::remove, std::sort and other mutating algorithms.
The difference between mutable and immutable iterators is not detected by iterator tag, it's determined by whether the assignment expressions are well-formed. So for example if you pass an iterator to std::sort that's immutable, then the algorithm won't compile anyway, so there's generally no need for an input iterator to also be tagged with output_iterator_tag. All algorithms that require an OutputIterator will Just Work with a mutable ForwardIterator, again there is no need for it to be tagged with output_iterator_tag.
If you have different needs from those of the standard algorithms then I can't immediately think of a reason that your proposal won't work for your iterators. But it won't detect mutable standard iterators. For example std::deque<int>::iterator and int* have iterator category random_access_iterator_tag, not your private tag and not anything to do with output_iterator_tag. So you would probably be better off defining your own traits class rather than hoping to adapt the existing iterator_traits::iterator_category to provide the information you want.

AnyIterator and boost iterator facade

Is it possible to implement an any iterator with boost iterator facade?
I don't want to define implementation details in my baseclass
class Base
{
public:
typedef std::vector<int>::iterator iterator;//implementation detail
...
virtual iterator begin()=0;
virtual iterator end()=0;
};
or do i have to write one completely from scratch;
The code you've posted has fixed the type of iterators returned from Base and all it's implementantions to std::vector<int>::iterator which is probably not what you want. Jeremiah's suggestion is one way to go with one drawback: you loose compatibility with STL... I know of three implementations of a polymorphic iterator wrapper:
becker's any_iterator (which implements boost::iterator_facade)
the opaque_iterator library (google for it), or
Adobe's very interesting poly library which contains a hierarchy of STL conforming any_iterators.
The problem is harder than it might seem... I made an attempt myself mainly because I needed covariance in any_iterators type argument (any_iterator<Derived> should be automatically convertible to any_iterator<Base>) which is difficult to implement cleanly with STL like iterators. A C# like Enumerator<T> is easier to implement(*) (and imho generally a cleaner concept than STL-like pairs of iterators) but again, you "loose" the STL.
(*) = without 'yield' of course :-)
I think this may be what you're looking for:
any_iterator: Type Erasure for C++ Iterators
Here's a snippet from that page::
Overview
The class template any_iterator is the analog to boost::function for
iterators. It allows you to have a single variable and assign to it
iterators of different types, as long as these iterators have a
suitable commonality.

Can 'iterator' type just subclass 'const_iterator'?

After another question about iterators I'm having some doubts about custom containers. In my container, iterator is a subclass of const_iterator, so that I get conversion from non-const to const "for free". But is this allowed or are there any drawbacks or non-working scenarios for such a setup?
Yes, this is fine. This is how VC10's implementation of the iterators for vector are structured, for example. See _Vector_iterator and _Vector_const_iterator in <vector>.
By the way, writing iterators is hard. It's worth your time to learn and use the boost::iterator library.
Subclassing seems strange to me here, but there is effectively an issue.
Even if you don't want to depend on Boost parts, check the Boost.Iterator library, and more especially the iterator_facade and iterator_adaptor bits.
There is a full-blown example of how to write an iterator and a const_iterator for your class without duplicating too much. Their idea is to write a template iterator_base class which you can then use for const and non-const types in the line of:
template <class Value> class iterator_base;
typedef iterator_base<T> iterator;
typedef iterator_base<const T> const_iterator;
The issue with subclassing is that you should then provide a virtual destructor and you're exposed to slicing (when building a const_iterator from an iterator)
So, unlike others here, I don't find it "fine".
Think about a case which will require you to modify the iterator's members.

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*)