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); });
Related
I have created a priority_queue with custom comparator which stores string in lexicographically sorted order, and it works as expected.[ Ref. this] ]
Now, I want it to be value in an unordered_map, and I got error: no matching constructor for initialization ... and closest thing I found is this. I realize I need to pass the comparator to the constructor as well, but how?
Here is my code as of now :
#include <iostream>
#include <vector>
#include <unordered_map>
#include <queue>
using namespace std; // Used to make code less verbose
int main() {
auto cmp = [](string s1, string s2){
return s1.compare(s2) > 0;
};
using myQuque = priority_queue<string, vector<string>, decltype(cmp)> ;
// This code works
myQuque pq(cmp);
pq.push("ZZ");
pq.push("AA");
pq.push("CC");
while(!pq.empty()){
cout << pq.top() << " ";
pq.pop();
}
// This doesn't. How do I pass 'cmp' to constructor?
unordered_map<string, myQuque> table;
auto p = table["r"];
p.push("ZZ");
p.push("AA");
}
https://godbolt.org/z/cvPfPd
I then realized that I can use multiset as well for this application, but I still would like to know how can I use priority_queue with custom comparator in map.
Using a lambda was a bad idea... just provide comparison through the comparison template argument, then no constructor argument is required...
#include <iostream>
#include <vector>
#include <unordered_map>
#include <queue>
using namespace std; // Used to make code less verbose
struct Cmp {
bool operator()(const string& s1, const string& s2) const {
return s1.compare(s2) > 0;
}
};
int main() {
using myQuque = priority_queue<string, vector<string>, Cmp>;
// This code works
myQuque pq;
pq.push("ZZ");
pq.push("AA");
pq.push("CC");
while(!pq.empty()){
cout << pq.top() << " ";
pq.pop();
}
// This doesn't. How do I pass 'cmp' to constructor?
unordered_map<string, myQuque> table;
auto p = table["r"];
p.push("ZZ");
p.push("AA");
}
Note too I've changed the comparison to take arguments by const reference, avoiding deep copying the text being compared for each comparison (at least whenever longer than any Short-String-Optimisation buffer your std::string implementation might have).
Maps use the default constructor when creating new elements. You could use pointers, but you’d need to allocate each new entry:
unordered_map<string, shared_ptr<myQuque>> table;
auto p = make_shared<myQueue>(cmp);
table["r"] = p;
p->push("ZZ");
p->push("AA");
Problem is that with custom run-time comparator, default constructor of myQuque is not available.
std::unordered_map::operator[] must be able to use default constructs for value in case there is no value ready for specyfic key. This is needed since it returns a reference to value which can be used in assignment expression.
To fix it you have to drop operator[], you can use this:
unordered_map<string, myQuque> table;
auto &p = table.emplace("r", cmp).first->second;
p.push("ZZ");
p.push("AA");
demo: https://godbolt.org/z/bPnrEe
As an alternative you can provide static comparator to priority_queue as Tony Delroys answer. In such case myQuque will have default constructor and problem vanishes.
From what I know, stack does not have iterators in C++. For example, this post (Does std::stack expose iterators?) explicitly states that stack does not have iterators. However, I was told by my supervisor that stack in c++ should have iterators since it is a standard data structure and you can do stack.begin() (However, from what I know, there's no such syntax in standard C++). How do I convince him? Why stack does not have iterators in C++?
Question#2: Thank you all for awesome answers. I think the question now comes down to: why doesn't it make sense to have iterators for stack?
You can convince your supervisor by advising your supervisor go and read section 23.6.5 of ISO/IEC-14882(2011), the specification for std::stack.
std::stack does not have iterators.
std::stack provides a strictly last-in-first-out view of the underlying container, and that's the point of it: to restrict the use of the underlying container to LIFO.
And so it does not provide iteration.
However, it does provide the underlying container as a protected member, which means that it's designed for being derived from. In your derived class you can provide iterators, and whatever you want. Also it's possible to just access that protected member of an ordinary std::stack, even without using any cast (namely via implicit conversion of member data pointer).
Re the added 2nd question,
” why doesn't it make sense to have iterators for stack?
It can make sense, but in most cases it would provide the non-LIFO access that std::stack is designed to remove, i.e. in most cases it would be at odds with the very purpose of std::stack.
For debugging, one's debugger will show the contents of a std::stack, so there's no big need to have direct support for doing it in code.
Example:
#include <iostream>
#include <stack>
namespace cppx {
using std::stack;
namespace hack {
template< class Item >
auto container_of( stack<Item> const& st )
-> typename stack<Item>::container_type const&
{
struct Hacked: stack<Item> { using stack<Item>::c; };
return st.*&Hacked::c;
}
} // namespace hack
template< class Item >
auto begin( stack<Item> const& st )
{ return hack::container_of( st ).begin(); }
template< class Item >
auto end( stack<Item> const& st )
{ return hack::container_of( st ).end(); }
} // namespace cppx
auto main()
-> int
{
using namespace std;
stack<int> st;
for( int const x : {3, 1, 4, 1, 5, 9, 2, 6, 5, 4} )
{
st.push( x );
}
using cppx::begin; using cppx::end;
for( auto it = begin( st ); it != end( st ); ++it )
{
cout << *it << " ";
}
cout << endl;
}
Since in this example begin and end are not placed in namespace std, a range based loop would not compile.
I didn't do that because the legality (validity) of specializing a standard function for a standard container, in namespace std, is an issue I don't want to get into here. I think it's not permitted, although specializing for one's own type would be OK. But I'm not sure.
std::stack is but a container adapter. It accepts a type of container (std::deque by default) as template parameter, and an instance of stack can be constructed from an instance of this container, but otherwise the underlying private container is not exposed and the stack itself does not have iteration facilities.
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).
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.
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.