C++ Is a std::string a container? - c++

This might be a simple question for some of you. But I was wondering if a std::string is a container. By container I mean the containers like for example std::vector, std::list and std::deque.
Since std::basic_string<> accepts other types than integral characters, but also is being optimized by working with character arrays. It isn't really clear to me in which category it falls.
This will compile:
#include <string>
#include <iostream>
int main() {
std::basic_string<int> int_str;
int_str.push_back(14);
return 0;
}
But by adding this line:
std::cout << int_str << std::endl;
It won't. So by these facts I could conclude that an std::basic_string was not intended to work with other types than characters.
It might be a strange question for you. The reason I need to know this is because I'm working on a framework and I'm still not able to determine in which category a "string" would fall.

Yes, the std::basic_string template fulfills all the requirements of the Container concept. However, I think it has stronger requirements on the contained type. Just trying to dig out exactly what.
(This is not Bjarne's Concepts. Just the bit of The Standard labeled "23.2.1 General container requirements".)

According to standards(2003,2011) std::basic_string is a container only for POD types.
I.e. fundamental types or plain structs/classes without constructors, destructors or virtual functions.
But gnu stdlib allow use non-POD types with std::basic_string. Here is an example of working with basic_string and non-POD types.
And if you what to make your example works you should define operator
std::ostream& operator<<(::std::ostream& out, std::basic_string<int> &dat)
{
out << dat[0];
return out;
}
Or something like that.

Well it is safe to say it is not a container at least not in the normal way you would think of an std container.
Most simple example is that you cant put any thing you want in it.
But it does have some classification of a container like the fact that you can put some of the basic types into it even if they are not chars, and perhaps most amazing thing is that you can get an iterator to it as if it was a normal container.
So is it a containr? I would say yes but! it is not an all genery one.

Related

Generic programming with ranges/views not templates?

I'd like to have function that accepts any container of a fixed type. For a example a function that will accept both std::array<float,1> and std::array<float,2>.
I thought this would be possible with ranges but I'm realizing my understanding is quite superficial.
I this possible without templates?
Edit: Can we define a type using the ranges library that will do the equivalent of span but will work for non-contiguous containers? Maybe I didn't phrase my question right, I probably meant view rather than container.
For contiguous ranges, you might use std::span (C++20):
void foo(std::span<float>)
{
// ...
}

Why is std::erase(std::erase_if) not a template in <algorithm> that works on any container?

std::erase(_if) is a nice addition to C++20(finally I can forget about obnoxious erase-remove idiom), but one thing is weird:
it is not a generic algorithm in a sense that it only works for std:: containers, e.g. it can not operate on boost vector.
#include<string>
#include<vector>
#include<boost/container/vector.hpp>
int main() {
std::string str = " Hello World !";
std::erase(str, ' '); // :)
boost::container::vector<int> vi{1,2};
std::erase(vi, 2); // :(
}
My best guess is that the algorithm was in experimental long before concepts were voted in standard so it was a lot of work to rework it, or that there was fear that concept for it could not be specified properly(i.e. it would work incorrectly on some user defined types with funky semantics).
So: my question is why is this not a generic algorithm in with some Concept(or enable_if) requirements/dispatching(e.g. for map/set)?
This is answered in the original proposal, N4009:
Q10. Instead of overloading erase_if() for each container, should you
provide a single erase_if(Container&, Predicate) function template
that's specified to do the right thing for each container?
A10. Such a general function template could be given user-defined
containers. There aren't any "container traits", so it's impossible to
determine whether a user-defined container is vector-like, list-like,
map-like, or something else. User-defined containers could simply be
rejected, but then the general function template wouldn't be doing
anything differently than the set of specific overloads being proposed
here. Note that an author of a user-defined container can overload
erase_if() for their container in their namespace.
TL;DR: because there's no way to write such "Concept(or enable_if) requirements/dispatching".

Python list equivalent in C++?

Could you please tell me what is the closest data type in C++ to python list? If there is nothing similar, how would you build it in C++?
If you're looking for standard one-dimensional data structures idiomatic to C++, std::vectors, std::lists, and arrays (or std::arrays) all have features similar to Python lists. Which of those data structure you want to choose depends on your requirements. std::vector is a very reasonable structure to default to if you're just looking to store a collection of items.
These data structures all require that each element is of the same type. Generally in C++ that is what you want. However, if you're specifically looking to store a variety of types in the same structure, there are a few options:
You can store void pointers. You will, however, need some way to figure out the type of each element and cast the pointer to the appropriate type to use each element.
If you have a specific set of types you wish to store, you can declare a union (which you'd generally wrap in a struct along with an enum to indicate the type being stored).
Maybe storing boost::any in a std::vector?
http://www.boost.org/doc/libs/1_54_0/doc/html/boost/any.html
Here is a simple working example. See James comments below too.
#include "../boost_1_54_0/boost/any.hpp"
#include <vector>
#include <string>
#include <iostream>
int main()
{
std::vector<boost::any> myList;
myList.push_back(std::string("Hello"));
myList.push_back(10);
myList.push_back(std::string("World"));
std::string any1 = boost::any_cast<std::string> (myList[0]);
int any2 = boost::any_cast<int> (myList[1]);
std::string any3 = boost::any_cast<std::string> (myList[2]);
std::cout<<any1<<" "<<any2<<" "<<any3<<std::endl;
return 0;
}
Actually no C++ container is equivalent to Python's list, which is partially a result of the very different object models of C++ and Python. In particular, the suggested and upvoted std::list is IMHO not even close to Python's list type, a I'd rather suggest std::vector or maybe std::deque. That said, it isn't clear what exactly it is that you want and how to "build it" strongly depends on what exactly "it" is, i.e. what you expect from the container.
I'd suggest you take a look at the C++ containers std::vector, std::deque and std::list to get an overview. Then look at things like Boost.Any and Boost.Variant that you can combine with them, maybe also one of the smart pointers and Boost.Optional. Finally, check out Boost.Container and Boost.Intrusive. If the unlikely case that none of these provide a suitable approximation, you need to provide a better explanation of what your actual goals are.
There is no real equivalent, and it would be extremely difficult
to provide one. Python and C++ are radically different
languages, and providing one really wouldn't make much sense in
the context of C++. The most important differences are that
everything in Python is dynamically allocated, and is an
"object", and that Python uses duck typing.
FWIW: one very early library (before templates) in C++ did offer
containers of Object*, with derived classes to box int,
double, etc. Actual experience showed very quickly that it
wasn't a good idea. (And I'm curious: does any one else
remember it? And particularly, exactly what it was
called---something with NHS in it, but I can't remember more.)
I am working on a wrapper for std::vector that makes it more like Python's lists named pylistpp. The API is just like Python. Example:
#include <list.hpp>
#include <iostream>
int main()
{
list<int> mylist;
mylist.append(5);
mylist.append(7);
int count = mylist.count(5);
std::cout << count << std::endl;
std::cout << mylist.pop(0) << std::endl;
std::cout << mylist.index(7);
return 0;
}

STL container requierments

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.

What is std::pair?

What is std::pair for, why would I use it, and what benefits does boost::compressed_pair bring?
compressed_pair uses some template trickery to save space. In C++, an object (small o) can not have the same address as a different object.
So even if you have
struct A { };
A's size will not be 0, because then:
A a1;
A a2;
&a1 == &a2;
would hold, which is not allowed.
But many compilers will do what is called the "empty base class optimization":
struct A { };
struct B { int x; };
struct C : public A { int x; };
Here, it is fine for B and C to have the same size, even if sizeof(A) can't be zero.
So boost::compressed_pair takes advantage of this optimization and will, where possible, inherit from one or the other of the types in the pair if it is empty.
So a std::pair might look like (I've elided a good deal, ctors etc.):
template<typename FirstType, typename SecondType>
struct pair {
FirstType first;
SecondType second;
};
That means if either FirstType or SecondType is A, your pair<A, int> has to be bigger than sizeof(int).
But if you use compressed_pair, its generated code will look akin to:
struct compressed_pair<A,int> : private A {
int second_;
A first() { return *this; }
int second() { return second_; }
};
And compressed_pair<A,int> will only be as big as sizeof(int).
std::pair is a data type for grouping two values together as a single object. std::map uses it for key, value pairs.
While you're learning pair, you might check out tuple. It's like pair but for grouping an arbitrary number of values. tuple is part of TR1 and many compilers already include it with their Standard Library implementations.
Also, checkout Chapter 1, "Tuples," of the book The C++ Standard Library Extensions: A Tutorial and Reference by Pete Becker, ISBN-13: 9780321412997, for a thorough explanation.
You sometimes need to return 2 values from a function, and it's often overkill to go and create a class just for that.
std:pair comes in handy in those cases.
I think boost:compressed_pair is able to optimize away the members of size 0.
Which is mostly useful for heavy template machinery in libraries.
If you do control the types directly, it's irrelevant.
It can sound strange to hear that compressed_pair cares about a couple of bytes. But it can actually be important when one considers where compressed_pair can be used. For example let's consider this code:
boost::function<void(int)> f(boost::bind(&f, _1));
It can suddenly have a big impact to use compressed_pair in cases like above. What could happen if boost::bind stores the function pointer and the place-holder _1 as members in itself or in a std::pair in itself? Well, it could bloat up to sizeof(&f) + sizeof(_1). Assuming a function pointer has 8 bytes (not uncommon especially for member functions) and the placeholder has one byte (see Logan's answer for why), then we could have needed 9 bytes for the bind object. Because of aligning, this could bloat up to 12 bytes on a usual 32bit system.
boost::function encourages its implementations to apply a small object optimization. That means that for small functors, a small buffer directly embedded in the boost::function object is used to store the functor. For larger functors, the heap would have to be used by using operator new to get memory. Around boost version 1.34, it was decided to adopt this optimization, because it was figured one could gain some very great performance benefits.
Now, a reasonable (yet, maybe still quite small) limit for such a small buffer would be 8 bytes. That is, our quite simple bind object would not fit into the small buffer, and would require operator new to be stored. If the bind object above would use a compressed_pair, it can actually reduce its size to 8 bytes (or 4 bytes for non-member function pointer often), because the placeholder is nothing more than an empty object.
So, what may look like just wasting a lot of thought for just only a few bytes actually can have a significant impact on performance.
It's standard class for storing a pair of values. It's returned/used by some standard functions, like std::map::insert.
boost::compressed_pair claims to be more efficient: see here
std::pair comes in handy for a couple of the other container classes in the STL.
For example:
std::map<>
std::multimap<>
Both store std::pairs of keys and values.
When using the map and multimap, you often access the elements using a pointer to a pair.
Additional info: boost::compressed_pair is useful when one of the pair's types is an empty struct. This is often used in template metaprogramming when the pair's types are programmatically inferred from other types. At then end, you usually have some form of "empty struct".
I would prefer std::pair for any "normal" use, unless you are into heavy template metaprogramming.
It's nothing but a structure with two variables under the hood.
I actually dislike using std::pair for function returns. The reader of the code would have to know what .first is and what .second is.
The compromise I use sometimes is to immediately create constant references to .first and .second, while naming the references clearly.
What is std::pair for, why would I use it?
It is just as simple two elements tuple. It was defined in first version of STL in times when compilers were not widely supporting templates and metaprogramming techniques which would be required to implement more sophisticated type of tuple like Boost.Tuple.
It is useful in many situations. std::pair is used in standard associative containers. It can be used as a simple form of range std::pair<iterator, iterator> - so one may define algorithms accepting single object representing range instead of two iterators separately.
(It is a useful alternative in many situations.)
Sometimes there are two pieces of information that you just always pass around together, whether as a parameter, or a return value, or whatever. Sure, you could write your own object, but if it's just two small primitives or similar, sometimes a pair seems just fine.