Copy/wrap vector<Class*> to vector<Class> - c++

Is there an std function to easily copy a vector of pointers to classes into a vector of classes or do I have to manually iterate over them?
Looking for the solution with the fastest/fewer lines of code :).
A solution that avoids copying without leaking memory is also welcomed!

I doubt there is such, below is one liner with for:
std::vector<X*> vec1 = { new X, new X };
std::vector<X> vec2;
vec2.reserve(vec1.size());
for (auto p : vec1) vec2.push_back(*p);
if you want to make sure no copies are made then you can use std::reference_wrapper<>:
std::vector<std::reference_wrapper<X>> vec2;
for (auto p : vec1) vec2.push_back(*p);
but then you have to make sure no element of vec2 is accessed after vec1 elements were deallocated.
Another aproach is to use unique_ptr like that:
std::vector<std::unique_ptr<X>> vec2;
for (auto p : vec1) vec2.emplace_back(p);
now you can ditch vec1, but then why not make vec1 of type std::vector<std::unique_ptr<X>>?

A one-liner with no manual iteration at all:
std::for_each(vec1.begin(), vec1.end(), [&](auto x) { vec2.push_back(*x); });
(Disclaimer: I'm not 100% sure about the reference-capturing lambda syntax.)

You have to do it yourself. std:transform or std::for_each will help you:
#include <algorithm>
#include <vector>
#include <functional>
using namespace std::placeholders;
class Myclass{};
Myclass deref(const Myclass *mc) { return *mc;}
void append(std::vector<Myclass> &v, Myclass *mc) {v.push_back(*mc);}
int main(){
std::vector<Myclass*> foo;
std::vector<Myclass> bar;
/* foo is initialised somehow */
/* bar is initialised somehow to hold the same amount of dummy elements */
//solution with transform
std::transform (foo.begin(), foo.end(), bar.begin(), deref);
bar={};
// solution with for_each
auto bound_append = std::bind(append, bar, _1);
std::for_each(foo.begin(), foo.end(), bound_append);
}
Compile wit -std=c++11 (gcc).

Related

Simplest way to assign std::span to std::vector

I wanted to do this
#include <vector>
#include <span>
struct S
{
std::vector<int> v;
void set(std::span<int> _v)
{
v = _v;
}
};
But it does not compile. What are the alternatives?
v.assign(_v.begin(), _v.end());
You can also use the std::vector::insert as follows:
v.insert(v.begin(), _v.begin(), _v.end());
Note that, if the v should be emptied before, you should call v.clear() before this. However, this allows you to add the span to a specified location in the v.
(See a demo)

Moving an std::unordered_map values to std::vector

Is there any way to move unordered_map values to a vector? All the ways I was able to find copy values (like in my example) instead of using something similar to std::move.
I would like to not copy values so I can retain uniqueness of shared_ptr foo, which I'll later change to unique_ptr.
class Class {
public:
std::shared_ptr <int> foo = std::shared_ptr <int> (new int (5));
};
int main() {
std::unordered_map <int, Class> mapOfObjects({
{1, Class()},
{2, Class()},
{3, Class()},
{4, Class()},
{5, Class()} });
std::vector <Class> someVector;
for (auto &object : mapOfObjects) {
someVector.push_back(object.second);
std::cout << "Is unique? " << ( someVector.back().foo.unique() ? "Yes." : "No.")
<< std::endl << std::endl;
}
}
Thank you in advance for all helpful answers.
You can certainly move shared_ptr from unordered_map to vector. All you need to do is to use std::move in your example:
someVector.push_back(std::move(object.second));
Keep in mind, after this operation, you might want to clear the map, as it now contains empty objects.
#SergeyA's answer already covers the essential part here, let me nevertheless add a solution based on range-v3, it shows where one part of the language is heading to with C++20.
#include <range/v3/view/map.hpp>
#include <range/v3/view/move.hpp>
using namespace ranges;
/* Setup mapOfObjects... */
const std::vector<Class> someVector = mapOfObjects | view::values | view::move;
The STL in its current shape isn't that bad either, but admittetly more verbose:
#include <algorithm>
#include <iterator>
std::vector<Class> someVector;
std::transform(std::move_iterator(mapOfObjects.begin()),
std::move_iterator(mapOfObjects.end()),
std::back_inserter(someVector),
[](std::pair<int, Class>&& entry){ return std::move(entry.second); });

Can a loop be avoided in this case?

I have a vector<A>, A has a field A::foo.
I would like to create a vector which elements are the "foo's" of the previous vector. Sure I can iterate through the vector's elements, but is there a direct implementation in the STL or other major library ?
Probably this should work
vector<A> vA; // this is your vector<A>, assumed to contain some `A`'s
...
vector<Foo> vFoo; // here is where we extract the Foo's
std::transform(std::begin(vA), std::end(vA), std::back_inserter(vFoo),
[](const A& param){return param.foo});
You can use std::transform from <algorithm>.
#include<algorithm>
std::vector<A> as;
// fill it
std::vector<A::foo_type> foos;
foos.resize(as.size());
std::transform(as.begin(), as.end(), foos.begin(), [](const &A) { return A.foo; });
You can use std::transform, but in this case,i think a range based for loop is more readable and should be at least as efficient as using STL's algorithm.
EDIT:
To illustrate my point:
struct Foo {};
struct Bar {
Foo foo;
};
int main() {
vector<Bar> bars(10);
vector<Foo> foos1, foos2, foos3;
foos1.reserve(bars.size());
for (const auto& e : bars) { // this will become 'for (e:bars)' in the future
foos1.push_back(e.foo);
}
foos2.resize(bars.size());
transform(bars.begin(), bars.end(), foos2.begin(), [](const Bar& bar) { return bar.foo; });
foos3.reserve(bars.size());
transform(bars.begin(), bars.end(), back_inserter(foos3), [](const Bar& bar){return bar.foo; });
}
In my opinion, the loop version is much easier to read (but I admit that this is probably a matter of taste).
Don't get me wrong, I really do like algorithms, but in very simple cases like this, their syntactic overhead just doesn't pull its weight.
EDIT2:
Some processors have a gather instruction instruction. It would be interesting to see, whether a typical compiler would generate those and under which conditions.

Initialisation of static vector

I wonder if there is the "nicer" way of initialising a static vector than below?
class Foo
{
static std::vector<int> MyVector;
Foo()
{
if (MyVector.empty())
{
MyVector.push_back(4);
MyVector.push_back(17);
MyVector.push_back(20);
}
}
}
It's an example code :)
The values in push_back() are declared independly; not in array or something.
Edit: if it isn't possible, tell me that also :)
In C++03, the easiest way was to use a factory function:
std::vector<int> MakeVector()
{
std::vector v;
v.push_back(4);
v.push_back(17);
v.push_back(20);
return v;
}
std::vector Foo::MyVector = MakeVector(); // can be const if you like
"Return value optimisation" should mean that the array is filled in place, and not copied, if that is a concern. Alternatively, you could initialise from an array:
int a[] = {4,17,20};
std::vector Foo::MyVector(a, a + (sizeof a / sizeof a[0]));
If you don't mind using a non-standard library, you can use Boost.Assignment:
#include <boost/assign/list_of.hpp>
std::vector Foo::MyVector = boost::list_of(4,17,20);
In C++11 or later, you can use brace-initialisation:
std::vector Foo::MyVector = {4,17,20};
With C++11:
//The static keyword is only used with the declaration of a static member,
//inside the class definition, not with the definition of that static member:
std::vector<int> Foo::MyVector = {4, 17, 20};
Typically, I have a class for constructing containers that I use (like this one from boost), such that you can do:
const list<int> primes = list_of(2)(3)(5)(7)(11);
That way, you can make the static const as well, to avoid accidental modifications.
For a static, you could define this in the .cc file:
// Foo.h
class Foo {
static const vector<int> something;
}
// Foo.cc
const vector<int> Foo::something = list_of(3)(5);
In C++Ox, we'll have a language mechanism to do this, using initializer lists, so you could just do:
const vector<int> primes({2, 3, 5, 7, 11});
See here.
You could try this one:
int arr[] = { 1,2,3,4,5,6,7,8,9 };
MyVector.insert(MyVector.begin(), arr, &arr[sizeof(arr)/ sizeof(*arr)]);
But it's probably only worth when you have a really long vector, and it doesn't look much nicer, either. However, you get rid of the repeated push_back() calls. Of course, if your values are "not in an array" you'd have to put them into there first, but you'd be able to do that statically (or at least references/pointers), depending on the context.
How about initializing using a static object. In its constuctor it
could call a static function in the object to do the initalization.
with boost you can use the +=() operator defined in the boost::assign namespace.
#include <boost/assign.hpp>
using namespace boost::assign;
int main()
{
static std::vector<int> MyVector;
MyVector += 4,17,20;
return 0;
}
or with static initialization:
#include <boost/assign.hpp>
using namespace boost::assign;
static std::vector<int> myVector = list_of(4)(17)(2);
int main()
{
return 0;
}
or even better, if your compiler supports C++ 11, use initialization lists.

How can I return a copy of a vector containing elements not in a set?

Suppose I have the following two data structures:
std::vector<int> all_items;
std::set<int> bad_items;
The all_items vector contains all known items and the bad_items vector contains a list of bad items. These two data structures are populated entirely independent of one another.
What's the proper way to write a method that will return a std::vector<int> contain all elements of all_items not in bad_items?
Currently, I have a clunky solution that I think can be done more concisely. My understanding of STL function adapters is lacking. Hence the question. My current solution is:
struct is_item_bad {
std::set<int> const* bad_items;
bool operator() (int const i) const {
return bad_items.count(i) > 0;
}
};
std::vector<int> items() const {
is_item_bad iib = { &bad_items; };
std::vector<int> good_items(all_items.size());
std::remove_copy_if(all_items.begin(), all_items.end(),
good_items.begin(), is_item_bad);
return good_items;
}
Assume all_items, bad_items, is_item_bad and items() are all a part of some containing class. Is there a way to write them items() getter such that:
It doesn't need temporary variables in the method?
It doesn't need the custom functor, struct is_item_bad?
I had hoped to just use the count method on std::set as a functor, but I haven't been able to divine the right way to express that w/ the remove_copy_if algorithm.
EDIT: Fixed the logic error in items(). The actual code didn't have the problem, it was a transcription error.
EDIT: I have accepted a solution that doesn't use std::set_difference since it is more general and will work even if the std::vector isn't sorted. I chose to use the C++0x lambda expression syntax in my code. My final items() method looks like this:
std::vector<int> items() const {
std::vector<int> good_items;
good_items.reserve(all_items.size());
std::remove_copy_if(all_items.begin(), all_items.end(),
std::back_inserter(good_items),
[&bad_items] (int const i) {
return bad_items.count(i) == 1;
});
}
On a vector of about 8 million items the above method runs in 3.1s. I bench marked the std::set_difference approach and it ran in approximately 2.1s. Thanks to everyone who supplied great answers.
As jeffamaphone suggested, if you can sort any input vectors, you can use std::set_difference which is efficient and less code:
#include <algorithm>
#include <set>
#include <vector>
std::vector<int>
get_good_items( std::vector<int> const & all_items,
std::set<int> const & bad_items )
{
std::vector<int> good_items;
// Assumes all_items is sorted.
std::set_difference( all_items.begin(),
all_items.end(),
bad_items.begin(),
bad_items.end(),
std::back_inserter( good_items ) );
return good_items;
}
Since your function is going to return a vector, you will have to make a new vector (i.e. copy elements) in any case. In which case, std::remove_copy_if is fine, but you should use it correctly:
#include <iostream>
#include <vector>
#include <set>
#include <iterator>
#include <algorithm>
#include <functional>
std::vector<int> filter(const std::vector<int>& all, const std::set<int>& bad)
{
std::vector<int> result;
remove_copy_if(all.begin(), all.end(), back_inserter(result),
[&bad](int i){return bad.count(i)==1;});
return result;
}
int main()
{
std::vector<int> all_items = {4,5,2,3,4,8,7,56,4,2,2,2,3};
std::set<int> bad_items = {2,8,4};
std::vector<int> filtered_items = filter(all_items, bad_items);
copy(filtered_items.begin(), filtered_items.end(), std::ostream_iterator<int>(std::cout, " "));
std::cout << std::endl;
}
To do this in C++98, I guess you could use mem_fun_ref and bind1st to turn set::count into a functor in-line, but there are issues with that (which resulted in deprecation of bind1st in C++0x) which means depending on your compiler, you might end up using std::tr1::bind anyway:
remove_copy_if(all.begin(), all.end(), back_inserter(result),
bind(&std::set<int>::count, bad, std::tr1::placeholders::_1)); // or std::placeholders in C++0x
and in any case, an explicit function object would be more readable, I think:
struct IsMemberOf {
const std::set<int>& bad;
IsMemberOf(const std::set<int>& b) : bad(b) {}
bool operator()(int i) const { return bad.count(i)==1;}
};
std::vector<int> filter(const std::vector<int>& all, const std::set<int>& bad)
{
std::vector<int> result;
remove_copy_if(all.begin(), all.end(), back_inserter(result), IsMemberOf(bad));
return result;
}
At the risk of appearing archaic:
std::set<int> badItems;
std::vector<int> items;
std::vector<int> goodItems;
for ( std::vector<int>::iterator iter = items.begin();
iter != items.end();
++iter)
{
int& item = *iter;
if ( badItems.find(item) == badItems.end() )
{
goodItems.push_back(item);
}
}
std::remove_copy_if returns an iterator to the target collection. In this case, it would return good_items.end() (or something similar). good_items goes out of scope at the end of the method, so this would cause some memory errors. You should return good_items or pass in a new vector<int> by reference and then clear, resize, and populate it. This would get rid of the temporary variable.
I believe you have to define the custom functor because the method depends on the object bad_items which you couldn't specify without it getting hackey AFAIK.