Does the standard require that some_container<T>::value_type be T?
I am asking because I am considering different approaches to implementing an STL-compliant 2d dynamic array. One of them is to have 2Darray<T>::value_type be 2Darray_row<T> or something like that, where the array would be iterated as a collection of rows (a little simplified. My actual implementation allows iteration in 3 directions)
The container requirements are a bit funky in the sense that they are actually not used by any generic algorithm. In that sense, it doesn't really matter much.
That said, the requirements are on the interface for containers not on how the container is actually instantiated. Even non-template classes can conform to the various requirements and, in fact, do. The requirement is that value_type is present; what it is defined to depends entirely on the container implementation.
Table 96 in §23.2.1 in the standard (c++11) requires a container class X containing objects of type T to return T for X::value_type.
So, if your some_container stores objects of type T, then value_type has to be T.
Either have a nested container (so colArray<rowArray<T> >) or have a single wrapping (2dArray<T>), but don't try to mix them. The nested approach allows you to use STL all the way down (vector<vector<T> >), but can be confusing and doesn't allow you column iterators etc, which you seem to want.
This SO answer addresses using ublas, and another suggests using Boost multi-arrays.
Generally, go for the STL or Boost option if you can. You are unlikely to write something as well by yourself.
Related
My question is really simple: Is there a type in the standard whose purpose is to store the begin-terator and the end-iterator for a container?
I want to return both iterators from a single function. I'm aware I could use std::pair for this but it feels like there would be some type in the standard for this exact purpose. I've scanned the <iterator> header but can't seem to find a type like this. I'm not that good at iterator terminology so I'm not sure if one of those actually do what I'm looking for. Is there one that does?
(If you're interested in why I even want to do it in the first place, I have constant arrays in a class template that derives from a base class. Using polymorphism I want to iterate over their class constants, but I obviously can't have the virtual functions of the base class return the actual arrays since those are templated. Hence, I have virtual functions returning plain pointers, called someArrayBegin(), someArrayEnd(), otherArrayBegin(), etc, that I override in the derived class template to return the correct addresses.)
Is there a type in the standard for storing the begin- and end-iterators of a container?
Your description matches closely with the concept of a range.
std::ranges::subrange can be created from a pair of iterators. That will be templated based on the iterator type.
If you need to hide the iterator type for runtime polymorphism, you would need ranges::any_view which unfortunately isn't in the standard implementation of the ranges. Furthermore, there is a runtime cost associated with it.
For contiguous containers, another alternative is std::span which can point to any contiguous range without the cost of type erasure. For strings in particular, yet another alternative is std::string_view.
I often use a slice structure in my projects:
struct SSlice {
void *pData;
size_t length;
};
Also I see other projects use similar containers to work with data w/o copying it (like RocksDB, MDB, etc...). Do anybody knows is there a standard (or OS-related) header with such container?
In STL, linux headers, no matter.
UPD. Main purpose of such container in my and mentioned projects is to work with data w/o copying it. E.g. I use it to parse URI path or LDAP DN and represent it as vector of slices.
It is more typical in C++ standard library, to use a range of iterators (begin, end), rather than an iterator and length (begin, length). Pointers are a case of iterator, which is a more general concept.
There exist no standard structure for ranges, nor slices† that you describe. The standard interfaces treat the begin and end as separate objects.
However, addition of ranges has been proposed and there exists a technical specification, that may already be supported by some standard library implementations.
† At least, not in general, but there is the special std::valarray container which provides a slice interface to its contents.
std::string_view is a C++17 non-owning view of a range of characters with std::string-like functionality. It is intended to speed oarsing, among other things.
span and array_view are names for various standarization and proto-standization efforts that also match your concept, but are not string-presuming.
I am reading about boost type erasure and I am trying to figure out the potential usage. I would like to practice it a bit while I am reading tons of documentations about the topic (it looks a big one). The most quoted area of application that is networking / exchanging data between client and server.
Can you suggest some other example or exercise where I can play I bit with this library?
Type Erasure is useful in an extraordinary amount of situations, to the point where it may actually be thought of as a fundamentally missing language feature that bridges generic and object oriented programming styles.
When we define a class in C++, what we are really defining is both a very specific type and a very specific interface, and that these two things do not necessarily need to be related. A type deals with the data, where as the interface deals with transformations on that data. Generic code, such as in the STL, doesn't care about type, it cares about interface: you can sort anything container or container-like sequence using std::sort, as long as it provides comparison and iterator interface.
Unfortunately, generic code in C++ requires compile time polymorphism: templates. This doesn't help with things which cannot be known until runtime, or things which require a uniform interface.
A simple example is this: how do you store a number of different types in a single container? The simplest mechanism would be to store all of the types in a void*, perhaps with some type information to distinguish them. Another way is to recognize all of these types have the same interface: retrieval. If we could make a single interface for retrieval, then specialize it for each type, then it would be as if part of the type had been erased.
any_iterator is another very useful reason to do this: if you need to iterate over a number of different containers with the same interface, you will need to erase the type of the container out of the type of the iterator. boost::any_range is a subtle enhancement of this, extending it from iterators to ranges, but the basic idea is the same.
In short, any time you need to go from multiple types with a similar interface to a single type with a single interface, you will need some form of type erasure. It is the runtime technique that equates compile time templates.
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.
Why would you need to overload the [] operator? I have never come across a practical scenario where this was necessary. Can somebody tell me a practical use case for this.
Err.. std::vector<t>, std::basic_string<t>, std::map<k, v>, and std::deque<t> ?
I used this for a class representing a registry key, where operator[] returned an object representing a registry value with the string between []s.
See also, the Spirit Parser Framework, which uses [] for semantic actions.
Any indexable container can usefully define operator[] to become usable in any template that uses []-syntax indexing.
You don't need that syntax sugar if you're not doing generic programming -- it may look nice, but, cosmetics apart, you could always define specific named methods such as getAt, setAt, and the like, with similar and simpler-to-code functionality.
However, generic programming is at the core of modern C++... and it bears an eerie resemblance to "compile-time, type-safe duck typing" (I'm biased towards such peculiar terminology, of course, having had a part in shaping it -- cfr wikipedia;-).
Just as you should try to use, e.g., prefix-* to mean "dereferencing" for all kinds of iterators and other pointer-like types (so they can be duck-typingly substituted for pointers in a template!), so similarly you should strive to define operator[] in container types where it makes sense, just so they can be duck-typingly substituted for arrays in appropriate templates.
It is useful if you implement almost any type of container that provides random access (or at least some form of keyed access) to its elements (e.g., consider std::vector).
If you write a class that inherits from another class that implements the [] operator, you might want to overwrite the [] operator, such as std::vector or std::string. If you don't do this, your class may not work as the user expects, as your class will implicitly inherit the parent's implementation of [].
Well, several STL containers give some examples - vector<> overloads it to make it act like an array. map<> for example provides the operator[] overload to provide an 'associative array'.
While it is not strictly necessary, it is incredibly useful in making user-defined containers or strings behave like builtin arrays or C strings. This cuts down on verbosity a lot (for example, in Java, you would have to use x.getElementAt(i) while in C++ you can use x[i]; similarly, in Java you need x.compareTo(y)<0, while in C++ you can achieve the same thing using x < y). It is syntactic sugar... but it is very, very tasty.