Since there are now generic iterator on c++ standard library like std::begin() and std::end(), I am wondering why there is no std::clear() method to clear a container?
The nice thing about std::begin/end is that it can be implemented for arrays. However it can only be implemented as namespace scope functions for arrays. Therefore in generic code it is nice to have std::begin/end so that the generic code doesn't have to decide whether it needs to use namespace scope or member functions when needing begin/end.
But I know of no such analogy for std::clear. It can only be implemented for containers which have member clear(). There is no dilemma for how to use it in generic code (at least not that I can think of).
Related
I've been wondering, is there any reason for the design decision in C++ to not have a pure abstract class for any of the std library containers?
I appreciate that hash_map came later from the stdext namespace but shares a very similar interface. In the event that I later decide I would like to implement my own map for a particular piece of software, I would have preferred to have some kind of interface to work with.
Example
std::base_map *foo = new std::map<std::string, std::string>;
delete foo;
foo = new stdext::hash_map<std::string, std::string>;
Obviously the above example is not possible, as far as I am aware, however this is similar for list and other std lib containers.
I appreciate that this is not C# or Java, but there is obviously no constraints in C++ to stop this design, so why was it designed like this so that there is no coupling between similar containers.
Because virtual functions add overhead.
Because the containers don't all have the same interface, there are common functions but also important differences regarding iterator invalidation and memory allocation (and so exception behaviour) which you need to understand, if you were using an abstract base you wouldn't know the specifics of how the concrete container would behave.
If you want to write code that is agnostic about the type of container it is passed then in C++ you write a template instead of relying on abstract interfaces, i.e. use static polymorphism not dynamic polymorphism. That avoids the overhead of dynamic dispatch and also allows specialization based on concrete type, because the concrete type is known at compile time.
Finally, it wouldn't have any advantage IMHO. It's better the way it is. As you say, this isn't C# or Java, thankfully.
(P.S. the stdext namespace is not part of C++, it appears to be Microsoft's namespace for non-standard types, a better example would use std::tr1::unordered_map or std::unordered_map instead of stdext::hash_map)
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.
It is fully safe to change boost::array to std::array? Can it cause any discrepancies?
Is boost::array better over std::array (performance?)?
std::array<T,N> and boost::array<T,N> are standard layout aggregates containing nothing but an array of T[N].
Their interaction with namespace boost and namespace std may be different (Specifically, ADL will find std functions for std::array, and boost functions for boost::array).
So, if there is a function foo in boost, calling foo(some_array) might work if some_array was from boost, and not if it was from std.
The only container algorithms currently in std are std::begin and std::end (and similar the new ones size empty etc if you include near-future ones). Ranges v3 (or whatever gets published) might add some more.
There are more container algorithms in boost than in std. Some of them might fail to build.
In the worst case, someone could write a function with the same name as a container algorithm in boost, with an argument that can implicitly convert from std::array, and the unqualified call to that function could result in a conversion after you change the variable type, while before it called the boost container algorithm.
Similarly, someone could write code that explicitly checks if a template argument is a boost::array and behave differently if it is.
Both of those are a bit of a stretch.
Finally, std::array has modern noexcept decoration, and boost has a public c_array member you can get at (the name std::array member variables is, I believe, not specified). (via #Potatoswatter). I'd personally expect std::array to have better support going forward, as boost::array mainly existed because std lacked the functionality.
Other than those corner cases, std::array should be a drop-in replacement.
Why are those C++11 new functions of header <string> (stod, stof, stoull) not member functions of the string class ?
Isn't more C++ compliant to write mystring.stod(...) rather than stod(mystring,...)?
It is a surprise to many, but C++ is not an Object-Oriented language (unlike Java or C#).
C++ is a multi-paradigm language, and therefore tries to use the best tool for the job whenever possible. In this instance, a free-function is the right tool.
Guideline: Prefer non-member non-friend functions to member functions (from Efficient C++, Item 23)
Reason: a member function or friend function has access to the class internals whereas a non-member non-friend function does not; therefore using a non-member non-friend function increases encapsulation.
Exception: when a member function or friend function provides a significant advantage (such as performance), then it is worth considering despite the extra coupling. For example even though std::find works really well, associative containers such as std::set provide a member-function std::set::find which works in O(log N) instead of O(N).
The fundamental reason is that they don't belong there. They
don't really have anything to do with strings. Stop and think
about it. User defined types should follow the same rules as
built-in types, so every time you defined a new user type,
you'd have to add a function to std::string. This would
actually be possible in C++: if std::string had a member
function template to, without a generic implementation, you
could add a specialization for each type, and call
str.to<double>() or str.to<MyType>(). But is this really
what you want. It doesn't seem like a clean solution to me,
having everyone writing a new class having to add
a specialization to std::string. Putting these sort of things
in the string class bastardizes it, and is really the opposite
of what OO tries to achieve.
If you were to insist on pure OO, they would have to be
members of double, int, etc. (A constructor, really. This
is what Python does, for example.) C++ doesn't insist on pure
OO, and doesn't allow basic types like double and int to
have members or special constructors. So free functions are
both an acceptable solution, and the only clean solution
possible in the context of the language.
FWIW: conversions to/from textual representation is always
a delicate problem: if I do it in the target type, then I've
introduced a dependency on the various sources and sinks of text
in the target type---and these can vary in time. If I do it in
the source or sink type, I make them dependent on the the type
being converted, which is even worse. The C++ solution is to
define a protocol (in std::streambuf), where the user writes
a new free function (operator<< and operator>>) to handle
the conversions, and counts on operator overload resolution to
find the correct function. The advantage of the free function
solution is that the conversions are part of neither the data
type (which thus doesn't have to know of sources and sinks) nor
the source or sink type (which thus doesn't have to know about
user defined data types). It seems like the best solution to
me. And functions like stod are just convenience functions,
which make one particularly frequent use easier to write.
Actually they are some utility functions and they don't need to be inside the main class. Similar utility functions such as atoi, atof are defined (but for char*) inside stdlib.h and they too are standalone functions.
So since it was introduced I have been loving the for each in keywords to iterate STL collections.(I'm a very very big fan of syntactic sugar).
My question is how can I write a custom collection that can be iterated using these keywords?
Essentially, what APi do I need to expose for my collections to be iterable using these keywords?
I apologize if this sounds blunt, but please do not respond with "use boost", "don't write your own collections", or the like. Pursuit of knowledge, my friends. If it's not possible, hey, I can handle that.
I'd also very much so prefer not to have to inject an STL iterator into my collections.
Thanks in advance!
Here is a good explanation of iterable data structures (Range-Based loops):
In order to make a data structure iterable, it must work similarly to the existing STL iterators.
There must be begin and end methods that operate on that structure,
either as members or as stand-alone functions, and that return iterators to
the beginning and end of the structure.
The iterator itself must support an operator* method, an operator != method, and an operator++ method, either as members or as stand-alone functions.
Note, in C++11 there is an integrated support for range-based loops without the use of STL, though the above conditions hold for this as well. You can read about it at the same link above.
It's not really clear from your quesiton whether you're talking about std::for_each defined in the <algorithm> header, or the range-based for loop introduced in C++11.
However, the answer is similar for both.
Both operate on iterators, rather than the collection itself.
So you need to
define an iterator type which satisfies the requirements placed on it by the STL (the C++ standard, really). (The main things are that it must define operator++ and operator*, and a couple of other operations and typedefs)
for std::for_each, there is no 2. You're done. You simply pass two such iterators to std::for_each. For the range-based for loop, you need to expose a pair of these iterators via the begin() and end() functions.
And... that's it.
The only tricky part is really creating an iterator which complies with the requirements. Boost (even though you said you didn't want to use it) has a library which aids in implementing custom iterators (Boost.Iterator). There is also the std::iterator class which is intended as a base class for custom iterator implementations. But neither of these are necessary. Both are just convenience tools to make it easier to create your own iterator.