An array-backed vector using allocator override - a bad idea? - c++

I recently started working with C++ again, after I worked with it in days of yore when the STL wasn't as popular. Well, the STL is great, but I need to wrap an array of mine in a vector for utilizing STL goodness - without copying anything. So, I read this SO question:
Wrapping dynamic array into STL/Boost container?
Surprisingly, most answers, including the accepted one, did not suggest a solution which actually yields a vector... I don't know, maybe coming living in the Java world for a while made me a fan of interfaces. Anyway, one answer by IdanK did suggest getting the vector 'class' (rather, the template) to accommodate this - replacing the allocator with code which uses the backing array.
I'm wondering why this isn't a widely-used solution, why it's not part of STL or Boost, why people don't link to typical implemenation. Are detriments to this approach which I'm failing to notice?

No, there is no standard way of turning
int a[34];
into
std::vector<int>
so you can pass it to a function like
void f(const std::vector<int>& v);
HOWEVER as I see it you have two options, either use a vector at the callsite as that is the type you utilmately need to use and it's adavantagous to a raw array in pretty much every way. Or modify the function to operator on iterators:
template<typename Iter>
void f(Iter first, Iter last);
Then that function can be used with vector, deques, sets, and even raw arrays like so:
std::set<int> s { 1,2,3,4 };
std::vector<int> v { 1,2,3,4 };
int ar[4] { 1,2,3,4 };
f(begin(ar), end(ar));
f(begin(v), end(v));
f(begin(s), end(s));
Personally I would do both though, use a vector at the callsite, and change your func to operate on iterators to decouple it from a particular container.
And to answer your question directly.
I'm wondering why this isn't a widely-used solution, why it's not part of STL or Boost, why people don't link to typical implemenation. Are detriments to this approach which I'm failing to notice?
It's not a widely catered to problem because the idiomatic way to do deal with the issue is to use a generic iterator interface. (Look at the interface to the containers, like std::vector::insert it doesn't take a vector but a pair of iterators).
EDIT:
If you have no other choices, then you're going to have to copy the data:
int arr[4];
//c++11
std::vector<int> v ( begin(arr), end(arr) );
//c++03
std::vector<int> v ( arr, arr+4 );

Related

Is it a good idea to extend std::vector?

Working slightly with javascript, I realized it is ways faster to develop compared with C++ which slows down writing for reasons which often do not apply. It is not comfortable to always pass .begin() and .end() which happens through all my application.
I am thinking about extending std::vector (more by encapsulation than inheritance) which can mostly follow the conventions of javascript methods such as
.filter([](int i){return i>=0;})
.indexOf(txt2)
.join(delim)
.reverse()
instead of
auto it = std::copy_if (foo.begin(), foo.end(), std::back_inserter(bar), [](int i){return i>=0;} );
ptrdiff_t pos = find(Names.begin(), Names.end(), old_name_) - Names.begin();
copy(elems.begin(), elems.end(), ostream_iterator<string>(s, delim));
std::reverse(a.begin(), a.end());
But, I was wondering if it is a good idea, why already there is no C++ library for such common daily functionality? Is there anything wrong with such idea?
There's nothing inheritly wrong with this idea, unless you try to delete a vector polymorphically.
For example:
auto myvec = new MyVector<int>;
std::vector<int>* myvecbase = myvec;
delete myvecbase; // bad! UB
delete myvec; // ok, not UB
This is unusual but could still be a source of error.
However, I would still not recommend it.
To gain your added functionalities, you'd have to have an instance of your own vector, which means you either have to copy or move any other existing vectors to your type. It disallows you to use your functions with a reference to a vector.
For example consider this code:
// Code not in your control:
std::vector<int>& get_vec();
// error! std::vector doesn't have reverse!
auto reversed = get_vec().reverse();
// Works if you copy the vector to your class
auto copy_vec = MyVector<int>{get_vec()};
auto reversed_copy = copy_vec.reverse();
Also, it will work with only vector, whereas I can see the utility to have these functionalities with other container types.
My advice would be to make your proposed function free - not make them member of your child class of vector. This will make them work with any instance or references, and also overloadable with other container types. This will make your code more standard ( not using your own set of containers ) and much easier to maintain.
If you feel the need to implement many of those functional style utilities for container types, I suggest you to seek a library that implements them for you, namely ranges-v3, which is on the way to standardisation.
On the other side of the argument, there are valid use case for inheriting STL's class. For example, if you deal with generic code and want to store function object that might be empty, you can inherit from std::tuple (privately) to leverage empty base class optimization.
Also, it happened to me sometime to store a specific amount of elements of the same type, which could vary at compile time. I did extended std::array (privately) to ease the implementation.
However note something about those two cases: I used them to ease the implementation of generic code, and I inherited them privately, which don't expose the inheritance to other classes.
A wrapper can be used to create a more fluent API.
template<typename container >
class wrapper{
public:
wrapper(container const& c) : c_( c ){}
wrapper& reverse() {
std::reverse(c_.begin(), c_.end());
return *this;
}
template<typename it>
wrapper& copy( it& dest ) {
std::copy(c_.begin(), c_.end(), dest );
return *this;
}
/// ...
private:
container c_;
};
The wrapper can then be used to "beautify" the code
std::vector<int> ints{ 1, 2, 3, 4 };
auto w = wrapper(ints);
auto out = std::ostream_iterator<int>(std::cout,", ");
w.reverse().copy( out );
See working version here.

How to initialize std stack with std vector?

I need to put an std::vector into an std::stack.
Here is my method so far(I am building a card game) :
void CardStack::initializeCardStack(std::vector<Card> & p_cardVector) {
m_cardStack = std::stack<Card>();
//code that should initialize m_cardStack with p_cardVector
}
Note : I cannot change my method signature because it is a imposed by a teacher...
Do I have to iterate over the whole vector ? What is the most efficient way to do this ? The documentation.
I have tried Jens answer but it didn't work.
std::stack doesn't have a constructor which accepts iterators, so you could construct a temporary deque and initialize the stack with this:
void ClassName::initializeStack(std::vector<AnotherClass> const& v) {
m_stackAttribute = std::stack<AnotherClass>( std::stack<AnotherClass>::container_type(v.begin(), v.end()) );
}
However, this copies each element into the container. For maximum efficiency, you should also use move-semantics to eliminate copies
void ClassName::initializeStack(std::vector<AnotherClass>&& v) {
std::stack<AnotherClass>::container_type tmp( std::make_move_iterator(v.begin()), std::make_move_iterator( v.end() ));
m_stackAttribute = std::stack<AnotherClass>( std::move(tmp) );
}
The most efficient way is not using an std::stack at all and just use a std::vector or even better for this use a std::deque.
I've seen and written a lot of C++ code (a lot) but I've yet to find any use for the stack stuff (any meaningful use, that is). It would be different if the underlying container could be changed or having its container type determined at runtime, but this is not the case.
To copy the elements from an std::vector into a std::deque you can just use
std::deque<T> stack(vec.begin(), vec.end());
This will allow the implementation to use the most efficient way to copy the elements.
To explicitly answer your question: yes, the only way to put elements in a stack is to push them in with a loop. This is not efficient but the stack interface doesn't define anything else. However who wrote code accepting an std::stack parameter should be fired (unless s/he promises that it will never happen again) and its code reverted to something more sensible: you would get the same (absence of) "flexibility" but a better interface.
The design problem of stack is that it's parametrized on the underlying container type while instead (to have any meaning) should have been parametrized on the contained element type and receving in the constructor a container for that type (thus hiding the container type). In its present form is basically useless.

Iterate over different collection types in a class

class MyClass {
std::vector<int> vi;
std::vector<string> vs;
}
I'd like to iterate over all the collections in MyClasswith a single iterator, i.e., iterate through all of vi, and then through all of vs. vs and vi don't have a 1:1 relationship (so i can't use a tuple based iteration approach). This was a programming question I came across.
The Iterator design pattern works on collections of the same type, abstracting the access from the internal representation. Its interface is a useful thing to emulate for this problem, but the type difference between the collections is what's giving me a hard time.
I like to approach the problem from the usage perspective.
MyClass mc;
... // push elements into mc
for( MyClassIterator it = mc.begin();
it != mc.end();
it++)
{
// *it can be either an int or a string
// operator * for the iterator cannot return a common type! :(
}
I'm not even sure how to think about the design for MyClassIterator because of the different types in the collections (int, string in the example).
Edit: Just to clarify, this was an programming question I came across. I couldn't come up with anything sensible/elegant, and hence I'm asking it here on SO.
You could make your iterator's value type a variant like Boost Variant.

Implement Iterators Even When Not Needed? C++

I have a container called "ntuple" that is essentially a C array and length. It's main purpose is to be the argument of multi-dimensional math functions. As of now, it's really fast and utilizes several constructors of the form
ntuple(double x, double y, double z)
{
size = 3;
vec = new double[size];
vec[0] = x;
vec[1] = y;
vec[2] = z;
}
And every time I work with a higher dimensional, yet known function, I just add a new constructor. I have on for an array as well:
ntuple(double* invec, long unsigned insizesize)
In order to make my code more compatible with regular c++ code, should I implement an ntuple iterator class? Nothing I've done has needed one and it seems like it will just slow everything down. But the more I read, the more vital it seems to use iterators for the sake of compatibility with standard C++ code.
I worry that when someone tries to work with my code, it won't mesh well with the standard techniques that they expect to use. But the purpose of my ntuple class is just to take arguments into functions.
Should I implement the iterators just as a precaution (if someone else will try to use the STL on it) at the cost of slowing my code?
Thanks.
Implementing iterators for a wrapper around a C array is trivial -- just return pointers to the first, and one-past-the-last, element for begin and end respectively, and adding non-virtual methods to a POD class won't slow down much of anything. Accessing the array via these methods won't be any slower than using array index lookups, and can be faster in some contexts. And if you don't use them, your code won't run slower.
As an advantage, in C++11 if you have a begin and end method, std::begin and std::end will find it, and for( auto x: container ) { /* code */ } will work on your type.
As this seems to be an X/Y problem, I suspect one of your problems is that you shouldn't be using your ntuple class at all. std::vector<double> is already a thin wrapper around a C-style array that is well written. To pass it without the cost of copying it, std::vector<double> const&.
As a pedantic aside, the STL refers to the library from which the template component of std was derived. It differs slightly from the std library in a few ways.
Yes, use vector but (if you really have lots of data in memory) be very careful to manage vector's memory. Then you will really have this 4 byte overhead (wasted for capacity).
allways create vector with explicit size, or create empty and use resize()
fill vector using indices (as you do vec[0] = ...)
never use push_back - it can request (twice) more memory than needed
You can also enforce this rules with inheriting vector (though sometimes this practice is not recommended) like this
class ntuple: public std::vector<double> {
private:
typedef std::vector<double> super;
void push_back(double); // do not implement
// also forbid pop_back()
public:
ntuble(double a, double b) {
resize(2);
(*this)[0] = a;
(*this)[1] = b;
}
ntuple(double* invec, long unsigned size)
: super(invec, invec + size)
{
}
// all your other convenient constructors here
};
iterators will still be accessible with begin() and end() methods

Best way to return list of objects in C++?

It's been a while since I programmed in C++, and after coming from python, I feel soooo in a straight jacket, ok I'm not gonna rant.
I have a couple of functions that act as "pipes", accepting a list as input, returning another list as output (based on the input),
this is in concept, but in practice, I'm using std::vector to represent the list, is that acceptable?
further more, I'm not using any pointers, so I'm using std::vector<SomeType> the_list(some_size); as the variable, and returning it directly, i.e. return the_list;
P.S. So far it's all ok, the project size is small and this doesn't seem to affect performance, but I still want to get some input/advice on this, because I feel like I'm writing python in C++.
The only thing I can see is that your forcing a copy of the list you return. It would be more efficient to do something like:
void DoSomething(const std::vector<SomeType>& in, std::vector<SomeType>& out)
{
...
// no need to return anything, just modify out
}
Because you pass in the list you want to return, you avoid the extra copy.
Edit: This is an old reply. If you can use a modern C++ compiler with move semantics, you don't need to worry about this. Of course, this answer still applies if the object you are returning DOES NOT have move semantics.
If you really need a new list, I would simply return it. Return value optimization will take care of no needless copies in most cases, and your code stays very clear.
That being said, taking lists and returning other lists is indeed python programming in C++.
A, for C++, more suitable paradigm would be to create functions that take a range of iterators and alter the underlying collection.
e.g.
void DoSomething(iterator const & from, iterator const & to);
(with iterator possibly being a template, depending on your needs)
Chaining operations is then a matter of calling consecutive methods on begin(), end().
If you don't want to alter the input, you'd make a copy yourself first.
std::vector theOutput(inputVector);
This all comes from the C++ "don't pay for what you don't need" philosophy, you'd only create copies where you actually want to keep the originals.
I'd use the generic approach:
template <typename InIt, typename OutIt>
void DoMagic(InIt first, InIt last, OutIt out)
{
for(; first != last; ++first) {
if(IsCorrectIngredient(*first)) {
*out = DoMoreMagic(*first);
++out;
}
}
}
Now you can call it
std::vector<MagicIngredients> ingredients;
std::vector<MagicResults> result;
DoMagic(ingredients.begin(), ingredients.end(), std::back_inserter(results));
You can easily change containers used without changing the algorithm used, also it is efficient there's no overhead in returning containers.
If you want to be really hardcore, you could use boost::tuple.
tuple<int, int, double> add_multiply_divide(int a, int b) {
return make_tuple(a+b, a*b, double(a)/double(b));
}
But since it seems all your objects are of a single, non-polymorphic type, then the std::vector is all well and fine.
If your types were polymorphic (inherited classes of a base class) then you'd need a vector of pointers, and you'd need to remember to delete all the allocated objects before throwing away your vector.
Using a std::vector is the preferably way in many situations. Its guaranteed to use consecutive memory and is therefor pleasant for the L1 cache.
You should be aware of what happends when your return type is std::vector. What happens under the hood is that the std::vector is recursive copied, so if SomeType's copy constructor is expensive the "return statement" may be a lengthy and time consuming operation.
If you are searching and inserting a lot in your list you could look at std::set to get logarithmic time complexity instead of linear. (std::vectors insert is constant until its capacity is exceeded).
You are saying that you have many "pipe functions"... sounds like an excellent scenario for std::transform.
Another problem with returning a list of objects (opposed to working on one or two lists in place, as BigSandwich pointed out), is if your objects have complex copy constructors, those will called for each element in the container.
If you have 1000 objects each referencing a hunk of memory, and they copy that memory on Object a, b; a=b; that's 1000 memcopys for you, just for returning them contained in a container. If you still want to return a container directly, think about pointers in this case.
It works very simple.
list<int> foo(void)
{
list<int> l;
// do something
return l;
}
Now receiving data:
list<int> lst=foo();
Is fully optimal because compiler know to optimize constructor of lst well. and
would not cause copies.
Other method, more portable:
list<int> lst;
// do anything you want with list
lst.swap(foo());
What happens: foo already optimized so there is no problem to return the value. When
you call swap you set value of lst to new, and thus do not copy it. Now old value
of lst is "swapped" and destructed.
This is the efficient way to do the job.