Refinement and inheritance in c++ - c++

what is refinement in c++?
while reading c++ primer plus i came across following statement:
in terms of the C++ language, this particular bidirectional iterator,
being a built-in type, couldn’t be derived from a class. Conceptually,
however, it does inherit. Some STL literature uses the term refinement
to indicate this conceptual inheritance. Thus, a bidirectional
iterator is a refinement of the forward iterator concept
how are inheritance and refinement related?

Refinement means something like "It has the same attributes (or features, or requirements), plus more."
If the Liskov Substitution Principle is followed, inheritance is usually refinement, because you can do all the base class things with a derived instance, and a derived instance satisfies all the base requirements.
Refinement does not have to be implemented using inheritance. This is partly due to C++ supporting static polymorphism, e.g. templates. A bidirectional iterator is a refinement of a forward iterator even if the former does not inherit from the latter, so long as programs can use a bidirectional iterator wherever a forward iterator is required. Functions which take iterators usually take them as template types, so all that matters is that they implement a known set of methods (e.g. increment and dereference for forward iterators, plus decrement for bidirectional).

Related

C++ 2a - polymorphic range

I am writing a C++ library and have had this amazing idea of using as much C++2a/C++20 as possible. Thus, I am using the standard library concepts and creating my own. However, the idea of a function returning a std::vector<X> seemed non-C++20 enough to me, so I declared in my concept a return type matching std::ranges::view<X>. I've then implemented some classes that fulfill this concept.
However, the problem appeared when I wanted to devise a polymorphic wrapper class. So, let's say the concept is C and I have three implementing classes C1, C2 and C3 (but allow for more). Now I want to create a class C_virtual and a template C_virtual_impl<C c> deriving from it, which will allow me to refer to all classes fulfilling C polymorphically. However, for that to work I need a polymorphic std::ranges::view wrapper, similar in spirit to C_virtual.
I have not seen any such class in the headers and in C++ reference. Moreover, when I started implementing it myself, I quickly found myself unable to due to some requirements on iterators, in particular default constructibility, swappability and similar.
Is there a nonobvious solution in the standard library or an idiom? If not, how do I deal with the problem? Possibly a change of design will work. I certainly do not want to return a std::vector<X> or to return a V<X> where V would be a type parameter of C. How do I do this?
Range views, and many other template techniques, are not meant to be used with inheritance-based polymorphism. This is much like how vector<BaseClass> is not especially useful.
If you need runtime polymorphism, then the tool you want is not inheritance (directly); it's type erasure. That is, you have some view wrapper which uses type erasure to forward the various view operations to the erased type. This would also need to be paired with type-erased iterators that wrap the iterators of the given view.
Now of course, this means that the characteristics of the view have to be defined by the type erased wrapper. The wrapper could implement the input_range concept, but it could never fulfill more than input_range itself. Even if you put a contiguous_range type in the wrapper, the wrapper will limit the interface to that of an input_range.
As such, it's best to just avoid this case and rely on static polymorphism via templates whenever possible.

Virtual parent for containers and 'iterable' class

I was wondering if there was a reason why there's no virtual parent inheritance for all std containers.
Since C++ is oop, I get some reason for using external function as such from algorithm header.
But i wonder why string does not have size() function ( doing the same as length ) for genericity?
Also, why is there no "iterable" class from which would iterables containers inherit ( because of the different types of iterator? )
This one come from my short experience with python. In my opinion, python's biggest strengh is how easy if is to use iterable.
EDIT:
To clarify myself: i know C++ is mutli-paradigm, but i would like to focus on containers. We could have keep C-style using struct and functions, why defining some as methods and others not? For encapsulation only?
Having both sequential and oop means is confusing and illogical i think
Why having begin(vec) and vec.begin() ?
And i speak about iterable, not iterators, and yes, iterator was a class in the std defining an iterface for iterator which is now deprecated ( and i understand why ). So iterators are object, why not doing iterable object ( juste to pack iterator begin and iterator end together if it is not to define virtual parent for iterable containers) ?
I hope i was clearer this time. I already got answer i thought about by myself for the most, but i would prefer an explanation about the current logic in the std.
Thank you for the time taken to read and answer.
I was wondering if there was a reason why there's no virtual parent inheritance for all std containers.
There is a cost attached to this (virtual dispatch is not free!), and most people (all people?) wouldn't need it.
In C++, you don't pay for what you don't use. (In theory.)
i wonder why string does not have size() function ( doing the same as length ) for genericity?
It does.
why is there no "iterable" class from which would iterables containers inherit ( because of the different types of iterator? )
Because we don't need one. You claim that C++ is "oop", but that is not true: it is multi-paradigm, and most of the standard library (particularly the parts inherited from the antique STL) are template based, not object-oriented.
This allows us to provide iterators that fit a set of "requirements", rather than those that fit some definition of "class". For example, pointers (which do not have class type!) are a valid kind of iterator.
This one come from my short experience with python. In my opinion, python's biggest strengh is how easy if is to use iterable.
That's reasonable. But C++ is not Python.
I was wondering if there was a reason why there's no virtual parent inheritance for all std containers.
Design decision at early stages of C++ standard forming. There is no much reason to do that - sure, you would have a nice common interface, but this can be also achieved with consistent standard managing (all containers already do have common set of functions without an explicit interface).
A disadvantage of a common base is that all containers would suddenly need virtual functions, and virtual functions are not free (more expensive at runtime than normal functions).
Since C++ is oop
It's not. C++ is a multiparadigm language. For example, you can have functions outside of any class (unlike Java, which is following OOP paradigm more strictly).
i get some reason for using external function as such from algorithm header.
A follow-up decision after the above. Having global functions accepting generic pair(s) of iterators allows to use any container (even user-defined) with these functions.
But i wonder why string does not have size() function ( doing the same as length ) for genericity?
It does have such a function and it always had. length() is another option, provided for better readability - it's more "English" to ask about length of string than to ask about size of string
Also, why is there no "iterable" class from which would iterables containers inherit ( because of the different types of iterator? ) This one come from my short experience with python. In my opinion, python's biggest strengh is how easy if is to use iterable.
There is one very good reason for that - iterators don't have to be of class type. Pointer type satisfies all of the requirements for RandomAccessIterator, but it is not a class.
C++ prefers compile-time polymorphism, suggesting you to use templates instead of virtual calls. Back in the good old days, it was more efficient (virtual calls are still not free).
There is however a certain level of standardization for containers: all of them support iterators, and standardized C++20 ranges are coming as well.

Tagged container - is mimicking the container's interface a good practice?

Assume I have a container type to which I would like to attach additional information. My approach would be to define a class holding the container and the info. Is it good practice to define methods for the new class which mimic the container's methods? E.g., instead of writing myContainerObject.internalVector[i] I would like to write myContainerObject[i]. One would have to redefine every method one wishes to use (size(), push_back() etc.). What are the drawbacks of such an approach? What alternatives exist (e.g., is inheriting from a container the better solution?).
You are using composition with forwarding functions, and it's the right thing to do with concrete classes like STL containers. One drawback is that you have to redefine every overload of every function you want to allow, only to forward arguments, as well as parrot-typedef nested types (like iterator).
An alternative is to inherit but never publicly, only with private inheritance (because STL containers' destructor is public and non-virtual), then use using-declarations inside the custom class to bring names of base-class functions and types into scope (needing only one using Base::name; for all overloads of a function).
Possible ways of grasping a type which is a container, that I can think of:
Provide the a decorator (this is what you are asking about) whose component will be the internal container. This is can work when you have strict interfaces which you must comply with. It's neither good or bad practice. Read about decorator design pattern.
Use an iterator concept in your algorithms instead of a container. This a generic approach, and how stl algorithms are implemented
Use a container concept - similar to (2). Detect if the type is a container (SFINAE trick) and manipulate it.
Reimplement the container interface. You need a really strong reason to do it since it requires a significant amount of work/know-how. Some info: http://stdcxx.apache.org/doc/stdlibug/16-3.html
Generally , unless your uses case is very, very trivial or you have some specific requirements you should not expose class internal state (myContainerObject.internalVector[i]) to out side world.
Best practice is to keep the internals private and implement the [] operator and other functions (size() and such).

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.

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