How to get std::set pointer to the raw data? - c++

I want to pass the whole set as an argument to a function, like the way we do for arrays (i.e &array[0]). I am not able to figure out how to get the pointer to the raw data for a set.

It is not possible to do it in the same way as an array because std::set is not required to have it's data arranged in a contiguous block of memory. It is a binary tree so it most likely consists of linked nodes. But you can pass it by reference, or use the begin() and end() iterators.
template <typename T>
void foo(const std::set<T>& s);
template <typename Iterator>
void bar(Iterator first, Iterator last);
std::set<int> mySet = ....;
foo(mySet);
bar(mySet.begin(), mySet.end());

You can't get a pointer to the raw data in the same sense as you'd do for an array, because a set doesn't reside in continuous memory.
I want to pass the whole set as an argument to a function
Pass it by reference. There's no memory overhead (if that's what you were worrying about):
void foo(std::set<int>& x);

You will have to iterate through the std::set to extract all the elements of the std::set.
Unlike std::vector and arrays there is no requirment imposed by the standard that std::set elements should be located in contiguos memory.
Either pass an reference/pointer to std::set in the function and extract the data inside the function by iterating over it.

It depends what you mean by:
"I want to pass the whole set as an argument to a function"
std::set<int> data;
// fill data;
You can pass the set by reference:
plop(data); // void plop(std::set<int>& data); // passing be reference would be the C++ way
Alternatively you can pass iterators.
This abstracts away the type of container you are using and thus allows the writers of plop() to concentrate on the algorithm. In this case the iterators behave in the same way as pointers (in C++ code).
plop(data.begin(), data.end(); // template<typename I> void plop(I begin, I end);
Alternatively do you mean you want to pass the data in a set to a C like function.
In this case you need to pass a pointer (as that is the only thing C can understand). Unfortunately you can not pass a pointer into a set directly as that has no real meaning. But you can copy the data into a vector and from there into a C program:
std::vector<int> datavec(data.begin(), data.end());
plop(&data[0], datavec.size()); // void plop(int* data, std::size_t size);
This works because vector stores the data in contiguous memory.

Related

Can the STL map comparator somehow get the pointer to the map itself?

can the STL map comparator somehow obtain the pointer to the map itself (or any other external parameter), in addition to pointers to the values being compared?
I want to use an STL map as an index into some binary data consisting of variable-length records, and I would prefer to just store offsets in the map, with the comparator looking up actual values using these offsets.
But for this to work, the comparator needs to know the base address of the data block (to add the offsets to). Using pointers instead of offsets is not an option, because the data block can be moved in memory. So I would prefer to store this base pointer in a subclass of std::map and retrieve it in the comparator. And for that, the comparator must somehow know the address of the map object. Is this possible?
I understand I can include a pointer to the map object into every map key, but it would waste memory. Is there a more straightforward method of doing it?
Thanks!
As mentioned in the comments, you can do this with a capturing lambda, e.g.:
#include <map>
struct map_data {};
int main ()
{
map_data md;
auto comparator = [&md] (int lhs, int rhs) { return lhs < rhs; };
std::map <int, int, decltype (comparator)> my_map (comparator);
my_map.find (5);
}
The base address of your binary data is then available within the lambda via &md.

Standard way of std::vector<double> borrowing the contents of a double[]

Is there a C++ (preferably C++11) standard-compliant idiom which I can employ to allow a std::vector<double> to borrow the contents of a double[] of known size?
I have a function (actually a functor masquerading as a callback from an optimiser) with prototype:
double MyFunctorClass::operator()(double s[]) const;
(MyFunctorClass also has m_size which reveals the number of elements of s).
I want to call a function that takes a const std::vector<double>& as an input.
One solution technique involves my creating a std::vector<double> member variable and somehow switching the double[] data into the data area of that std::vector, call the function, then switch it back to the caller. I'd rather not copy due to performance concerns: it is the objective function. Any ideas?
No, you cannot do that.
std::vector allocates space for stored content on the heap (and owns it), so you cannot force it to use your own memory.
By 'use your own memory' I mean 'your own memory with valid content, which is preserved and never touched by the container unless you explicitly say so'. Of course, you can define your own memory allocation policy by overriding 'allocator' parameter, but that is not a solution in this case.
Change you function to accept templated begin and end iterators
instead of void foo( std::vector<double> vd )
use template<typename Iter> void foo( Iter begin, Iter end )
This will let you pass in any standard container or pointers.
iterate like so:
while( begin!=end ) {
/*const?*/ double& value = *begin;
// whatever you were going to do
++begin;
}
If the double[] you want to temporarily store into the vector has no particular allocation constraints, you can use a second std::vector<double> and use std::swap(vec1, vec2) for quick elements exchange. Then to obtain a double[] from any of the vectors just do &vec[0].
Notice that I don't think that swapping is guaranteed to preserve the addresses of the internal arrays (although I cannot think of any implementation that doesn't). Edit: it's actually guaranteed (see comments).

keeping track of vector elements addresses

I want to know if there is a way to keep track of addresses of elements in a vector.
I like to use vector of solid elements like std::vector<MyObject> vec because:
std::vector do all the allocation / deallocation stuff for me
it also ensures me that my elements are stored in contiguous memory
I can get benefits of all code that work with vectors (e.g. <algorithm>)
This is exactly what I want. The problem arises when I want to store the address / reference of elements of my vector in other objects. In fact, the problem really arises when std::vector need to reallocate memory.
I tried to find alternatives to my problem:
Use vector of pointers / smart pointers : No, the pointers will be allocated contiguously but not the elements
Use vector of pointers / smart pointers and write my own operator new/new[] for MyObject : Humm, that seems better but no. By using a vector to allocate my elements I can say : "those particular set (I do not refer here to std::set) of elements must be allocated contiguously, not all". In fact I may want to have other set of elements that should be allocated contiguously because of the way I want to use them and using a vector to do that is exactly what (I think) I need. Thats also implies that I'm doing the job I want the vector to do.
Why not using boost multi-index? : In some ways that will do what I want because I want to store pointers/smartpointers of my vector elements in other containers. But no again because I really want to store reference/pointer/smartpointer of my vector's elements inside other objects, not just other containers.
What I would loved to have is a vector that can give me a pointer object that will allways point the the address of the desired element and I will use it like that :
std::vector<MyObject> vec;
// insert some elements
...
// get a pointer object by index or by using an iterator
// does something like that exist?
std::vector<MyObject>::pointer ptr = vec.get_pointer_at(5);
// do what I want on the vector except removing the element
...
// use my pointer whatever reallocations occurred or not
ptr->doSomething();
That sounds like an iterator that will never be invalidated except the fact I don't need/want to perform arithmetic on it (+x, -x, ++, --).
So, can someone leads me to the way to achieve what I want or explain me why/where I'm wrong wanting to do this? Please accept my apologize for my lack of knowledge in STL if there is a well known solution that I missed / or if this question has already be answered.
Edit:
I think that if I have to code such kind of pointer, that means that I'm wanting something useless or I'm wrong somewhere (unless someone should have already wrote a template for that) . So I'm more looking to a validated C++ idiom to get rid of this problem.
Although std::vector does not give you such pointer, there is no reason why you cannot make one yourself. All it takes is a class that keeps a reference to the std::vector object and the index, and overloads the prefix operator * and the infix operator -> (you need four overloads - const and non-const for each operator).
You would use this pointer like this:
std::vector<int> vect = {2, 4, 6, 8, 10, 12, 14, 16};
vect_ptr<int> ptr(vect, 5); // <<== You need to implement this
*ptr = 123;
cout << *ptr << endl;
The implementation of these overloads would grab the std::vector's begin() iterator, and return the result of calling vect.at(index). This would look like a pointer from the outside, but the object to which it points would change as the content of the std::vector gets resized.
As far as I know, there is nothing in the standard library nor in Boost to address your problem. A solution would be to implement your own kind of element pointer:
template<typename T>
class vector_element
{
public:
vector_element( std::vector<T>& v, std::size_t i )
: m_container( v ), m_element_index(i)
{ }
T& operator*() { return m_container[m_element_index]; }
T* operator->() { return &m_container[m_element_index]; }
private:
std::vector<T>& m_container;
std::size_t m_element_index;
};

Checking whether element exists in a Vector

I have a vector and it is going to hold 10 objects maximum. When I create the vector I believe it creates 10 "blank" objects of the class it will hold. Therefore I have a problem because my code relies on checking that a vector element is null and obviously it is never null.
How can I check whether a vector object contains an element I inserted, or one of the default constructor "blank" objects upon initialisation?
Is there a technique round this?
(I need to check for null because I am writing a recursive algorithm and the termination point, when the recursive function returns is when an object in the vector is null)
An instance of a class cannot be null. Only a pointer.
You do, however, have size() that you can use.
typedef stdd::vector<SomeClass> vec;
//define some vec, v
for (vec::size_type i = 0, s = vec.size(); i < s; ++i) {
//do something with v[i]
}
With a recursive function you could use this idea by passing along a maximum index.
void recursiveFunc(vec& v, vec::size_type s);
Then when checking your condition to recurse, you would need to check "am I at the end of the vector?"
Alternatively, instead of working on indexes, you could use iterators:
template <typename Iterator>
void recursiveFunc(Iterator begin, const Iterator& end);
If done correctly (and if possible in your situation), this could decouple your manipulation from being aware of the underlying data being stored in a vector.
The loop to go over the vector would then look like:
while (begin != end) {
//do something with *begin
++begin;
}
std::vector only inserts "real" objects. It (at least normally) allocates raw memory, and uses placement new to construct objects in that memory as needed. The only objects it'll contain will be the ones you put there.
Of course, if you want to, you can create a vector containing a number of copies of an object you pass to the constructor. Likewise, when you resize a vector, you pass an object it'll copy into the new locations if you're making it larger.
Neither of those is really the norm though. In a typical case, you'll just create a vector, which will start out containing 0 objects. You'll use push_back to add objects to the vector. When you search through the vector, the only objects there will be the ones you put there with push_back, and you don't need to worry about the possibility of it containing any other objects.
If you just want to check whether the vector is empty, you can just use:
if (your_vector.empty())
...which will (obviously enough) return true if it's empty, and false if it contains at least one object.
As #Corbin mentioned, size() will return the number of elements in the vector. It is guaranteed not to have any holes in between(contiguous), so you assured vector[vector.size()] is empty.

Hybrid vector/list container?

I'm in need of a container that has the properties of both a vector and a list. I need fast random access to elements within the container, but I also need to be able to remove elements in the middle of the container without moving the other elements. I also need to be able to iterate over all elements in the container, and see at a glance (without iteration) how many elements are in the container.
After some thought, I've figured out how I could create such a container, using a vector as the base container, and wrapping the actual stored data within a struct that also contained fields to record whether the element was valid, and pointers to the next/previous valid element in the vector. Combined with some overloading and such, it sounds like it should be fairly transparent and fulfill my requirements.
But before I actually work on creating yet another container, I'm curious if anyone knows of an existing library that implements this very thing? I'd rather use something that works than spend time debugging a custom implementation. I've looked through the Boost library (which I'm already using), but haven't found this in there.
If the order does not matter, I would just use a hash table mapping integers to pointers. std::tr1::unordered_map<int, T *> (or std::unordered_map<int, unique_ptr<T>> if C++0x is OK).
The hash table's elements can move around which is why you need to use a pointer, but it will support very fast insertion / lookup / deletion. Iteration is fast too, but the elements will come out in an indeterminate order.
Alternatively, I think you can implement your own idea as a very simple combination of a std::vector and a std::list. Just maintain both a list<T> my_list and a vector<list<T>::iterator> my_vector. To add an object, push it onto the back of my_list and then push its iterator onto my_vector. (Set an iterator to my_list.end() and decrement it to get the iterator for the last element.) To lookup, look up in the vector and just dereference the iterator. To delete, remove from the list (which you can do by iterator) and set the location in the vector to my_list.end().
std::list guarantees the elements within will not move when you delete them.
[update]
I am feeling motivated. First pass at an implementation:
#include <vector>
#include <list>
template <typename T>
class NairouList {
public:
typedef std::list<T> list_t;
typedef typename list_t::iterator iterator;
typedef std::vector<iterator> vector_t;
NairouList() : my_size(0)
{ }
void push_back(const T &elt) {
my_list.push_back(elt);
iterator i = my_list.end();
--i;
my_vector.push_back(i);
++my_size;
}
T &operator[](typename vector_t::size_type n) {
if (my_vector[n] == my_list.end())
throw "Dave's not here, man";
return *(my_vector[n]);
}
void remove(typename vector_t::size_type n) {
my_list.erase(my_vector[n]);
my_vector[n] = my_list.end();
--my_size;
}
size_t size() const {
return my_size;
}
iterator begin() {
return my_list.begin();
}
iterator end() {
return my_list.end();
}
private:
list_t my_list;
vector_t my_vector;
size_t my_size;
};
It is missing some Quality of Implementation touches... Like, you probably want more error checking (what if I delete the same element twice?) and maybe some const versions of operator[], begin(), end(). But it's a start.
That said, for "a few thousand" elements a map will likely serve at least as well. A good rule of thumb is "Never optimize anything until your profiler tells you to".
Looks like you might be wanting a std::deque. Removing an element is not as efficient as a std::list, but because deque's are typically created by using non-contiguous memory "blocks" that are managed via an additional pointer array/vector internal to the container (each "block" would be an array of N elements), removal of an element inside of a deque does not cause the same re-shuffling operation that you would see with a vector.
Edit: On second though, and after reviewing some of the comments, while I think a std::deque could work, I think a std::map or std::unordered_map will actually be better for you since it will allow the array-syntax indexing you want, yet give you fast removal of elements as well.