consume element from std::set [duplicate] - c++

This question already has answers here:
Is it possible to move an item out of a std::set?
(2 answers)
Closed 5 months ago.
I try to directly consume elements from a set, which i cannot get to work from the outside getting an error
binding reference of type ‘int&&’ to ‘std::remove_reference<const int&>::type’ {aka ‘const int’} discards qualifiers
Consuming from a vector works perfectly fine.
I really do not understand where syntactic the difference would be between consuming from the set or the vector, as they work similar cocerning their iterators.
I can make a Workaround pops(), however, I do not neccessarily see this as a intuitive solution.
#include <vector>
#include <set>
#include <iostream>
class A {
public:
std::vector<int> intv_{1,2,3};
std::set<int> ints_{1,2,3};
int pops() {
auto rslt = std::move(*ints_.begin());
ints_.erase(ints_.begin());
return rslt;
}
};
using namespace std;
void consume_int(bool dummy, int&& i) {
cout << i << endl;
}
using namespace std;
int main() {
A a;
consume_int(true, std::move( *(a.intv_.begin()) )); //OK!
a.intv_.erase(a.intv_.begin());
consume_int(true, std::move( *a.ints_.begin() )); //FAIL to compile
a.ints_.erase(a.ints_.begin());
consume_int(true, std::move(a.pops())); //Workaround OK!
return 0;
}

The point is: You are not allowed to change the objects within a set, as this would require to move their location within the set. This is why the iterator only returns a const reference even for non-const std::set!
Now r-value references are intended to be used to modify the object (moving the contents away – which would be such an illegal change of the set entry! – at that point the set cannot know that you are going to erase the entry anyway), and you cannot assign const references to, which would open doors to all such illegal modifications (of set members, objects in non-writable memory sections, etc).
Edit: Still you actually can move elements out of a std::set, provided you have at least C++17 available, in this case you can profit from the extract function:
int pops()
{
auto handle = ints_.extract(ints_.begin());
auto rslt = std::move(handle.value()); // for DEMONSTRATION purposes!
return rslt;
}
with the handle getting discarded on exiting the function – though, actually you don't need to explicitly move anything at all, you can simply write:
int pops()
{
auto handle = ints_.extract(ints_.begin());
return handle.value();
// or as a one-liner:
return ints_.extract(ints_.begin()).value();
}

Related

Type agnostic abstraction to handle forward and reverse iterators and ranges using the same runtime interface?

By design forward and reverse iterators and ranges are fundamentally different types. This is nice in the compile time optimization that it allows for. Sometimes it would be nice to hide that type difference behind an abstraction that allows them to be passed to the same run-time interface.
Are there any adapters in boost or the stl that make this easy? (ideally but not strictly C++11)
The following code shows both the known/expected failure and the desired hypothetical:
#include <boost/range.hpp>
#include <vector>
using Ints = std::vector<int>;
void real(boost::iterator_range<Ints::iterator> range){}
void fake(boost::agnostic_range<Ints::iterator> range){} // imaginary desired
int main()
{
auto ints = Ints{1,2,3,4,5};
real(boost::make_iterator_range(ints.begin(), ints.end()));
real(boost::make_iterator_range(ints.rbegin(), ints.rend())); // Error
fake(boost::make_agnsotic_range(ints.begin(), ints.end())); // imaginary
fake(boost::make_agnsotic_range(ints.rbegin(), ints.rend())); // imaginary
return 0;
}
Yes! Boost::any_range type erases the iterated object type and exposes only the output type and the iterator access type.
Note that the type erasure here requires a call through a virtual function to dereference the iterator so there's a performance cost there, but as long as non-trivial operations are performed inside the loop, this cost will be likely irrelevant.
BUG WARNING: boost::range had a big bug between ~1.55ish until release 1.74 (2020-08) which would cause access to destroyed items being passed through any_range that would cause UB (undefined behavior/probably crash) The work around to this exists in the code below where you explicitly pass the so-called reference type though the template parameters as const which causes some of the internal machinery to avoid tripping over the mistake.
#include <boost/range/adaptor/type_erased.hpp>
#include <boost/range/adaptor/reversed.hpp>
#include <boost/range/any_range.hpp>
#include <vector>
#include <list>
#include <iostream>
// note const int bug workaround
using GenericBiDirIntRange =
boost::any_range<int, boost::bidirectional_traversal_tag, const int>;
void possible(GenericBiDirIntRange const &inputRange) {
for(auto item: inputRange)
std::cout << item << "\n";
}
// note const int bug workaround
using type_erased_bi =
boost::adaptors::type_erased<int, boost::bidirectional_traversal_tag, const int>;
using reversed = boost::adaptors::reversed;
auto main() -> int {
auto intVec = std::vector<int>{1, 2, 3, 4};
auto intList = std::list<int>{1, 2, 3, 4};
possible(intVec | type_erased_bi());
possible(intList | reversed | type_erased_bi());
return 0;
}

is there a cleaner way to right operator[]() for a vector? [duplicate]

If I define a pointer to an object that defines the [] operator, is there a direct way to access this operator from a pointer?
For example, in the following code I can directly access Vec's member functions (such as empty()) by using the pointer's -> operator, but if I want to access the [] operator I need to first get a reference to the object and then call the operator.
#include <vector>
int main(int argc, char *argv[])
{
std::vector<int> Vec(1,1);
std::vector<int>* VecPtr = &Vec;
if(!VecPtr->empty()) // this is fine
return (*VecPtr)[0]; // is there some sort of ->[] operator I could use?
return 0;
}
I might very well be wrong, but it looks like doing (*VecPtr).empty() is less efficient than doing VecPtr->empty(). Which is why I was looking for an alternative to (*VecPtr)[].
You could do any of the following:
#include <vector>
int main () {
std::vector<int> v(1,1);
std::vector<int>* p = &v;
p->operator[](0);
(*p)[0];
p[0][0];
}
By the way, in the particular case of std::vector, you might also choose: p->at(0), even though it has a slightly different meaning.
return VecPtr->operator[](0);
...will do the trick. But really, the (*VecPtr)[0] form looks nicer, doesn't it?
(*VecPtr)[0] is perfectly OK, but you can use the at function if you want:
VecPtr->at(0);
Keep in mind that this (unlike operator[]) will throw an std::out_of_range exception if the index is not in range.
There's another way, you can use a reference to the object:
#include <iostream>
#include <vector>
using namespace std;
int main()
{
vector<int> v = {7};
vector<int> *p = &v;
// Reference to the vector
vector<int> &r = *p;
cout << (*p)[0] << '\n'; // Prints 7
cout << r[0] << '\n'; // Prints 7
return 0;
}
This way, r is the same as v and you can substitute all occurrences of (*p) by r.
Caveat: This will only work if you won't modify the pointer (i.e. change which object it points to).
Consider the following:
#include <iostream>
#include <vector>
using namespace std;
int main()
{
vector<int> v = {7};
vector<int> *p = &v;
// Reference to the vector
vector<int> &r = *p;
cout << (*p)[0] << '\n'; // Prints 7
cout << r[0] << '\n'; // Prints 7
// Caveat: When you change p, r is still the old *p (i.e. v)
vector<int> u = {3};
p = &u; // Doesn't change who r references
//r = u; // Wrong, see below why
cout << (*p)[0] << '\n'; // Prints 3
cout << r[0] << '\n'; // Prints 7
return 0;
}
r = u; is wrong because you can't change references:
This will modify the vector referenced by r (v)
instead of referencing another vector (u).
So, again, this only works if the pointer won't change while still using the reference.
The examples need C++11 only because of vector<int> ... = {...};
You can use it as VecPrt->operator [] ( 0 ), but I'm not sure you'll find it less obscure.
It is worth noting that in C++11 std::vector has a member function 'data' that returns a pointer to the underlying array (both const and non-const versions), allowing you to write the following:
VecPtr->data()[0];
This might be an alternative to
VecPtr->at(0);
which incurs a small runtime overhead, but more importantly it's use implies you aren't checking the index for validity before calling it, which is not true in your particular example.
See std::vector::data for more details.
People are advising you to use ->at(0) because of range checking. But here is my advise (with other point of view):
NEVER use ->at(0)! It is really slower. Would you sacrifice performance just because you are lazy enough to not check range by yourself? If so, you should not be programming in C++.
I think (*VecPtr)[0] is ok.

How to store references to objects from one vector in another vector in C++?

I've got a vector std::vector<MyClass> myclass_vec(10) with 10 initialized objects of MyClass. Now I would like to loop over this vector and store a reference to every MyClass object in another vector std::vector<MyClass> myclass_vec_refs. The reason why I would like to store references is so because I don't have to copy the objects and obviously, refer to the same object as in myclass_vec.
For some reason, this doesn't work out as aspected. Do I have to declare std::vector<&MyClass> myclass_vec_refs like so?
As I was looking through other questions asked here I read about std::unique_ptr. If I change std::vector<std::unique_ptr<MyClass>> myclass_vec(10) then I wouldn't able to have a reference or pointer in myclass_vec_refs since they are declared unique. Correct me please if I'm mistaken.
Another approach was using std::shared_ptr. Since it holds a reference counter I would be able to have myclass_vec_refs point to objects in myclass_vec, but I read this introduces quite some overhead and share_ptr should only be used as a last resort.
I also don't know if referencing like I'm attempting works out. What happens if an object in myclass_vec is deleted? Is the myclass_vec_refs vector resized by -1 since the object doesn't exist anymore or is it just pointing to bad memory?
Is it possible to emplace_back a reference in the myclass_vec_refs vector? Since this creates the object in-place I guess this doesn't work and only push_back can be used?
You cannot make a vector of references.
Why?
A reference must refer to an actual object at all times, and vectors by design must be able to create "empty" objects (i.e. default constructor) dynamically for you.
You can however create a vector of pointers.
If the other vector is modified in any way, your pointers will become invalid.
If this is a problem to you, use a map or set instead.
As answered here: Strange Template Deduction
The trick is to use std::reference_wrapper<>
#include <algorithm>
#include <iostream>
#include <vector>
template<typename container_ty_, class Comp>
auto where(container_ty_& V, Comp&& comp)
{
using value_type = typename container_ty_::value_type;
using reference =
std::conditional_t<
std::is_const<container_ty_>::value,
std::reference_wrapper<const value_type>,
std::reference_wrapper<value_type>
>;
std::vector<reference> cursor;
for(auto& VAL : V)
if(comp(VAL))
cursor.push_back(VAL);
return cursor;
}
int main(int argc, char** argv) {
std::vector<int> tVect = {0, 5, 2, 1, 7, 9};
//Why must std::vector<int> be passed...
auto vec = where(tVect, [](const int& V) -> bool { return V > 5; });
std::for_each(vec.begin(), vec.end(), [] (int& v) { std::cout << v++ << std::endl; });
std::cout << std::endl;
std::for_each(tVect.begin(), tVect.end(), [](const int& v) { std::cout << v << std::endl; });
}

Interface for returning a bunch of values

I have a function that takes a number and returns up to that many things (say, ints). What's the cleanest interface? Some thoughts:
Return a vector<int>. The vector would be copied several times, which is inefficient.
Return a vector<int>*. My getter now has to allocate the vector itself, as well as the elements. There are all the usual problems of who has to free the vector, the fact that you can't allocate once and use the same storage for many different calls to the getter, etc. This is why STL algorithms typically avoid allocating memory, instead wanting it passed in.
Return a unique_ptr<vector<int>>. It's now clear who deletes it, but we still have the other problems.
Take a vector<int> as a reference parameter. The getter can push_back() and the caller can decide whether to reserve() the space. However, what should the getter do if the passed-in vector is non-empty? Append? Overwrite by clearing it first? Assert that it's empty? It would be nice if the signature of the function allowed only a single interpretation.
Pass a begin and end iterator. Now we need to return the number of items actually written (which might be smaller than desired), and the caller needs to be careful not to access items that were never written to.
Have the getter take an iterator, and the caller can pass an insert_iterator.
Give up and just pass a char *. :)
In C++11, where move semantics is supported for standard containers, you should go with option 1.
It makes the signature of your function clear, communicating that you just want a vector of integers to be returned, and it will be efficient, because no copy will be issued: the move constructor of std::vector will be invoked (or, most likely, Named Return Value Optimization will be applied, resulting in no move and no copy):
std::vector<int> foo()
{
std::vector<int> v;
// Fill in v...
return v;
}
This way you won't have to deal with issues such as ownership, unnecessary dynamic allocations, and other stuff which are just polluting the simplicity of your problem: returning a bunch of integers.
In C++03, you may want to go with option 4 and take an lvalue reference to a non-const vector: standard containers in C++03 are not move-aware, and copying a vector may be expensive. Thus:
void foo(std::vector<int>& v)
{
// Fill in v...
}
However, even in that case, you should consider whether this penalty is really significant for your use cases. If it is not, you may well opt for a clearer function signature at the expense of some CPU cycles.
Also, C++03 compilers are capable of performing Named Return Value Optimization, so even though in theory a temporary should be copy-constructed from the value you return, in practice no copying is likely to happen.
You wrote it yourself:
... This is why STL algorithms typically avoid allocating memory, instead wanting it passed in
except that STL algorithms don't typically "want memory passed in", they operate on iterators instead. This is specifically to decouple the algorithm from the container, giving rise to:
option 8
decouple the value generation from both the use and storage of those values, by returning an input iterator.
The easiest way is using boost::function_input_iterator, but a sketch mechanism is below (mostly because I was typing faster than thinking).
Input iterator type
(uses C++11, but you can replace the std::function with a function pointer or just hard-code the generation logic):
#include <functional>
#include <iterator>
template <typename T>
class Generator: public std::iterator<std::input_iterator_tag, T> {
int count_;
std::function<T()> generate_;
public:
Generator() : count_(0) {}
Generator(int count, std::function<T()> func) : count_(count)
, generate_(func) {}
Generator(Generator const &other) : count_(other.count_)
, generate_(other.generate_) {}
// move, assignment etc. etc. omitted for brevity
T operator*() { return generate_(); }
Generator<T>& operator++() {
--count_;
return *this;
}
Generator<T> operator++(int) {
Generator<T> tmp(*this);
++*this;
return tmp;
}
bool operator==(Generator<T> const &other) const {
return count_ == other.count_;
}
bool operator!=(Generator<T> const &other) const {
return !(*this == other);
}
};
Example generator function
(again, it's trivial to replace the lambda with an out-of-line function for C++98, but this is less typing)
#include <random>
Generator<int> begin_random_integers(int n) {
static std::minstd_rand prng;
static std::uniform_int_distribution<int> pdf;
Generator<int> rv(n,
[]() { return pdf(prng); }
);
return rv;
}
Generator<int> end_random_integers() {
return Generator<int>();
}
Example use
#include <vector>
#include <algorithm>
#include <iostream>
int main()
{
using namespace std;
vector<int> out;
cout << "copy 5 random ints into a vector\n";
copy(begin_random_integers(5), end_random_integers(),
back_inserter(out));
copy(out.begin(), out.end(),
ostream_iterator<int>(cout, ", "));
cout << "\n" "print 2 random ints straight from generator\n";
copy(begin_random_integers(2), end_random_integers(),
ostream_iterator<int>(cout, ", "));
cout << "\n" "reuse vector storage for 3 new ints\n";
out.clear();
copy(begin_random_integers(3), end_random_integers(),
back_inserter(out));
copy(out.begin(), out.end(),
ostream_iterator<int>(cout, ", "));
}
return vector<int>, it will not be copied, it will be moved.
In C++11 the right answer is to return the std::vector<int> is to return it, ensuring that it will be either explicitly or implicitly moved. (Prefer implicit move, because explicit move can block some optimizations)
Amusingly, if you are concerned about reusing the buffer, the easiest way is to throw in an optional parameter that takes a std::vector<int> by value like this:
std::vector<int> get_stuff( int how_many, std::vector<int> retval = std::vector<int>() ) {
// blah blah
return retval;
}
and, if you have a preallocated buffer of the right size, just std::move it into the get_stuff function and it will be used. If you don't have a preallocated buffer of the right size, don't pass a std::vector in.
Live example: http://ideone.com/quqnMQ
I'm uncertain if this will block NRVO/RVO, but there isn't a fundamental reason why it should, and moving a std::vector is cheap enough that you probably won't care if it does block NRVO/RVO anyhow.
However, you might not actually want to return a std::vector<int> - possibly you just want to iterate over the elements in question.
In that case, there is an easy way and a hard way.
The easy way is to expose a for_each_element( Lambda ) method:
#include <iostream>
struct Foo {
int get_element(int i) const { return i*2+1; }
template<typename Lambda>
void for_each_element( int up_to, Lambda&& f ) {
for (int i = 0; i < up_to; ++i ) {
f( get_element(i) );
}
}
};
int main() {
Foo foo;
foo.for_each_element( 7, [&](int e){
std::cout << e << "\n";
});
}
and possibly use a std::function if you must hide the implementation of the for_each.
The hard way would be to return a generator or a pair of iterators that generate the elements in question.
Both of these avoid the pointless allocation of the buffer when you only want to deal with the elements one at a time, and if generating the values in question is expensive (it might require traversing memory
In C++98 I would take a vector& and clear() it.

How to pass a vector to another vector push back? (without creating a extra variable to pass)

Well I am questioning myself if there is a way to pass a vector directly in a parameter, with that I mean, like this:
int xPOS = 5, yPOS = 6, zPOS = 2;
//^this is actually a struct but
//I simplified the code to this
std::vector <std::vector<int>> NodePoints;
NodePoints.push_back(
std::vector<int> {xPOS,yPOS,zPOS}
);
This code ofcourse gives an error; typename not allowed, and expected a ')'
I would have used a struct, but I have to pass the data to a Abstract Virtual Machine where I need to access the node positions as Array[index][index] like:
public GPS_WhenRouteIsCalculated(...)
{
for(new i = 0; i < amount_of_nodes; ++i)
{
printf("Point(%d)=NodeID(%d), Position(X;Y;Z):{%f;%f;%f}",i,node_id_array[i],NodePosition[i][0],NodePosition[i][1],NodePosition[i][2]);
}
return 1;
}
Ofcourse I could do it like this:
std::vector <std::vector<int>> NodePoints;//global
std::vector<int> x;//local
x.push_back(xPOS);
x.push_back(yPOS);
x.push_back(zPOS);
NodePoints.push_back(x);
or this:
std::vector <std::vector<int>> NodePoints;//global
std::vector<int> x;//global
x.push_back(xPOS);
x.push_back(yPOS);
x.push_back(zPOS);
NodePoints.push_back(x);
x.clear()
but then I'm wondering which of the two would be faster/more efficient/better?
Or is there a way to get my initial code working (first snippet)?
Use C++11, or something from boost for this (also you can use simple v.push_back({1,2,3}), vector will be constructed from initializer_list).
http://liveworkspace.org/code/m4kRJ$0
You can use boost::assign as well, if you have no C++11.
#include <vector>
#include <boost/assign/list_of.hpp>
using namespace boost::assign;
int main()
{
std::vector<std::vector<int>> v;
v.push_back(list_of(1)(2)(3));
}
http://liveworkspace.org/code/m4kRJ$5
and of course you can use old variant
int ptr[1,2,3];
v.push_back(std::vector<int>(ptr, ptr + sizeof(ptr) / sizeof(*ptr));
If you don't have access to either Boost or C++11 then you could consider quite a simple solution based around a class. By wrapping a vector to store your three points within a class with some simple access controls, you can create the flexibility you need. First create the class:
class NodePoint
{
public:
NodePoint( int a, int b, int c )
{
dim_.push_back( a );
dim_.push_back( b );
dim_.push_back( c );
}
int& operator[]( size_t i ){ return dim_[i]; }
private:
vector<int> dim_;
};
The important thing here is to encapsulate the vector as an aggregate of the object. The NodePoint can only be initialised by providing the three points. I've also provided operator[] to allow indexed access to the object. It can be used as follows:
NodePoint a(5, 6, 2);
cout << a[0] << " " << a[1] << " " << a[2] << endl;
Which prints:
5 6 2
Note that this will of course throw if an attempt is made to access an out of bounds index point but that's still better than a fixed array which would most likely seg fault. I don't see this as a perfect solution but it should get you reasonably safely to where you want to be.
If your main goal is to avoid unnecessary copies of vector<> then here how you should deal with it.
C++03
Insert an empty vector into the nested vector (e.g. Nodepoints) and then use std::swap() or std::vector::swap() upon it.
NodePoints.push_back(std::vector<int>()); // add an empty vector
std::swap(x, NodePoints.back()); // swaps contents of `x` and last element of `NodePoints`
So after the swap(), the contents of x will be transferred to NodePoints.back() without any copying.
C++11
Use std::move() to avoid extra copies
NodePoints.push_back(std::move(x)); // #include<utility>
Here is the explanation of std::move and here is an example.
Both of the above solutions have somewhat similar effect.