473,322 Members | 1,562 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,322 software developers and data experts.

referring contents of another container.

Hi,
I am facing problem some times, and not finding a suitable answer to
solve it.
I have a vector (or some other container, sometimes) of some class,
named CC
like vector<CCv, NOT vector<CC*;

I want another class say Segment to refer a portion of this vector. I
can't store the iterator for vector as a member function to the class,
as
1) The iterators have different invalidation strategy, and may
invalidate the stored iterators when some new elements are added to the
vector.
2) The iterators are not default constructible, where I need to
calculate the range after Segment class is formed.

Someone suggested, storing raw index of the position, as size_t, and
construct iterator from that. But that looks little error prone.

Things are much easy if I use vector<shared_ptr<CC rather than
vector<CC, where I can copy a portion of the vector inside Segment,
as it copies only the pointers (Which looks much like Java collections,
list, subList etc ). However, I want the vector to store CC directly
like vector<CC>,
and Segment to use a reference of the portion (like
vector<shared_ptr<CC , as vector<CC&is not possible , or vector
<CC*also not possible as the elements in a vector are movable and may
invalidate the pointer , or use iterators).

In actual case, lots of different hierarchical views are associated
with the vector<CCall of them points to a range in the vector.
Hope, the problem statement is understandable. If needed, I will be
able to supply more detail.
Looking for an elegant solution.
Thanks in advance.
abir

Nov 13 '06 #1
8 1388
toton wrote:
....
Looking for an elegant solution.
Have you considered using a std::list ?

There is also another container posted by Martin Knoblauch on
comp.std.c++ recently that may be better.

Nov 13 '06 #2
toton wrote:
Hi,
I am facing problem some times, and not finding a suitable answer to
solve it.
I have a vector (or some other container, sometimes) of some class,
named CC
like vector<CCv, NOT vector<CC*;

I want another class say Segment to refer a portion of this vector. I
can't store the iterator for vector as a member function to the class,
as
1) The iterators have different invalidation strategy, and may
invalidate the stored iterators when some new elements are added to the
vector.
2) The iterators are not default constructible, where I need to
calculate the range after Segment class is formed.

What's wrong with:

vector<CCv(10);

vector<CC*v_ref;
v_ref.push_back(&v[2]);
v_ref.push_back(&v[3]);
v_ref.push_back(&v[4]);

v_ref[0]->some_CC_memfun();

Notice that the all CC objects are owned by v. v_ref merely references
some of the elements assuming the pointers are valid within its
(v_ref's) life time.

Regards,
Ben
Nov 13 '06 #3

benben wrote:
toton wrote:
Hi,
I am facing problem some times, and not finding a suitable answer to
solve it.
I have a vector (or some other container, sometimes) of some class,
named CC
like vector<CCv, NOT vector<CC*;

I want another class say Segment to refer a portion of this vector. I
can't store the iterator for vector as a member function to the class,
as
1) The iterators have different invalidation strategy, and may
invalidate the stored iterators when some new elements are added to the
vector.
2) The iterators are not default constructible, where I need to
calculate the range after Segment class is formed.


What's wrong with:

vector<CCv(10);

vector<CC*v_ref;
v_ref.push_back(&v[2]);
v_ref.push_back(&v[3]);
v_ref.push_back(&v[4]);

v_ref[0]->some_CC_memfun();

Notice that the all CC objects are owned by v. v_ref merely references
some of the elements assuming the pointers are valid within its
(v_ref's) life time.
Thanks. This is very much what I need.
But the questions are,
If v resizes (and increases) , and hence moves the elements whether
still v_ref will have a reference ? Is it true for any other container?
I know that instead of v_ref, If I store iterator begin_ = v.begin()+1
and, iterator end_ = v.begin()+3; they are no more valid when v
resizes, and increases size.
And instead of manual pushback like this, is there a way to use std
copy algorithm which will copy the pointers ?
Regards,
Ben
Nov 13 '06 #4

toton wrote:
benben wrote:
toton wrote:
Hi,
I am facing problem some times, and not finding a suitable answer to
solve it.
I have a vector (or some other container, sometimes) of some class,
named CC
like vector<CCv, NOT vector<CC*;
>
I want another class say Segment to refer a portion of this vector. I
can't store the iterator for vector as a member function to the class,
as
1) The iterators have different invalidation strategy, and may
invalidate the stored iterators when some new elements are added to the
vector.
2) The iterators are not default constructible, where I need to
calculate the range after Segment class is formed.

What's wrong with:

vector<CCv(10);

vector<CC*v_ref;
v_ref.push_back(&v[2]);
v_ref.push_back(&v[3]);
v_ref.push_back(&v[4]);

v_ref[0]->some_CC_memfun();

Notice that the all CC objects are owned by v. v_ref merely references
some of the elements assuming the pointers are valid within its
(v_ref's) life time.
Thanks. This is very much what I need.
But the questions are,
If v resizes (and increases) , and hence moves the elements whether
still v_ref will have a reference ? Is it true for any other container?
I know that instead of v_ref, If I store iterator begin_ = v.begin()+1
and, iterator end_ = v.begin()+3; they are no more valid when v
resizes, and increases size.
deque is closest to vector and may be implemented
the same.

Better solution is to use list or, if the problem
fits, ::boost::multi_index instead.
And instead of manual pushback like this, is there a way to use std
copy algorithm which will copy the pointers ?
You can do that with transform and something like:

template<class T>
T * ptr_of(T & t){ return &t; }

template<class It1, class It2>
void transform_to_ptr(It1 begin, It1 end, It2 out)
{
::std::transform
( begin, end, out
, ::boost::bind( &ptr_of<typename It1::value_type>, _1)
);
}

void sampl()
{
::std::vector<intv;
::std::fill_n( ::std::back_inserter(v), 100, 10);

::std::vector<int*v1;
transform_to_ptr( v.begin(), v.end(), ::std::back_inserter(v1) );
}

Regards,
Ben
Nov 13 '06 #5
toton wrote:
benben wrote:
>toton wrote:
>>Hi,
I am facing problem some times, and not finding a suitable answer to
solve it.
I have a vector (or some other container, sometimes) of some class,
named CC
like vector<CCv, NOT vector<CC*;

I want another class say Segment to refer a portion of this vector. I
can't store the iterator for vector as a member function to the class,
as
1) The iterators have different invalidation strategy, and may
invalidate the stored iterators when some new elements are added to the
vector.
2) The iterators are not default constructible, where I need to
calculate the range after Segment class is formed.

What's wrong with:

vector<CCv(10);

vector<CC*v_ref;
v_ref.push_back(&v[2]);
v_ref.push_back(&v[3]);
v_ref.push_back(&v[4]);

v_ref[0]->some_CC_memfun();

Notice that the all CC objects are owned by v. v_ref merely references
some of the elements assuming the pointers are valid within its
(v_ref's) life time.
Thanks. This is very much what I need.
But the questions are,
If v resizes (and increases) , and hence moves the elements whether
still v_ref will have a reference ? Is it true for any other container?
I know that instead of v_ref, If I store iterator begin_ = v.begin()+1
and, iterator end_ = v.begin()+3; they are no more valid when v
resizes, and increases size.
I hope I understand your problem. It is true that once v moves the
elements the pointers in v_ref will no-longer be valid. But there is not
much you can do because generally you can't have a pointer that points
to a moving object.

Iterators, much like pointers, are also invalidated if you make
insertion or erasure to the vector. Sometimes vectors move objects when
it wants to resize.

If you only want to reference a range, you can use the index:

template <typename C>
class segment
{
public:
typedef typename C::size_type size_type;
typedef typename C::iterator iterator;
typedef typename C::const_iterator const_iterator;
// ...

private:
size_type lower, upper;
C& container;

public:
explicit segment(C& c, size_type l, size_type u)
: container(c), lower(l), upper(u){}

iterator begin(){return container.begin()+lower;}
iterator end(){return container.begin() + upper;}

const_iterator begin() const;
const_iterator end() const;

// ...
};

vector<intv(10);
segment<vector<int s(v, 2, 5); // 2nd, 3rd and 4th elements
for_each(s.begin(), s.end(), some_op);

For more daring design you can write your own iterator type that has
range checks...
And instead of manual pushback like this, is there a way to use std
copy algorithm which will copy the pointers ?
Don't know the quickest way but what's in my head is

template <typename T>
T* address_of(T& t){return &t;}

std::transform(v.begin()+2, v.begin()+5, v_ref.begin(), address_of);
>
>Regards,
Ben
Ben
Nov 13 '06 #6

benben wrote:
toton wrote:
benben wrote:
toton wrote:
Hi,
I am facing problem some times, and not finding a suitable answer to
solve it.
I have a vector (or some other container, sometimes) of some class,
named CC
like vector<CCv, NOT vector<CC*;

I want another class say Segment to refer a portion of this vector. I
can't store the iterator for vector as a member function to the class,
as
1) The iterators have different invalidation strategy, and may
invalidate the stored iterators when some new elements are added to the
vector.
2) The iterators are not default constructible, where I need to
calculate the range after Segment class is formed.

What's wrong with:

vector<CCv(10);

vector<CC*v_ref;
v_ref.push_back(&v[2]);
v_ref.push_back(&v[3]);
v_ref.push_back(&v[4]);

v_ref[0]->some_CC_memfun();

Notice that the all CC objects are owned by v. v_ref merely references
some of the elements assuming the pointers are valid within its
(v_ref's) life time.
Thanks. This is very much what I need.
But the questions are,
If v resizes (and increases) , and hence moves the elements whether
still v_ref will have a reference ? Is it true for any other container?
I know that instead of v_ref, If I store iterator begin_ = v.begin()+1
and, iterator end_ = v.begin()+3; they are no more valid when v
resizes, and increases size.

I hope I understand your problem. It is true that once v moves the
elements the pointers in v_ref will no-longer be valid. But there is not
much you can do because generally you can't have a pointer that points
to a moving object.

Iterators, much like pointers, are also invalidated if you make
insertion or erasure to the vector. Sometimes vectors move objects when
it wants to resize.

If you only want to reference a range, you can use the index:

template <typename C>
class segment
{
public:
typedef typename C::size_type size_type;
typedef typename C::iterator iterator;
typedef typename C::const_iterator const_iterator;
// ...

private:
size_type lower, upper;
C& container;

public:
explicit segment(C& c, size_type l, size_type u)
: container(c), lower(l), upper(u){}

iterator begin(){return container.begin()+lower;}
iterator end(){return container.begin() + upper;}

const_iterator begin() const;
const_iterator end() const;

// ...
};

vector<intv(10);
segment<vector<int s(v, 2, 5); // 2nd, 3rd and 4th elements
for_each(s.begin(), s.end(), some_op);
So I came to the same point! . It is my current implementation ! Only
thing in my mind is, to me it looks "too raw", and was not sure if it
is the proper way of doing the thing.
However if it can be done in this way, I will continue using this.
For more daring design you can write your own iterator type that has
range checks...
Some static assert I always include. But may not need a dynamic range
checking, as all of the codes use begin & end only.
And instead of manual pushback like this, is there a way to use std
copy algorithm which will copy the pointers ?

Don't know the quickest way but what's in my head is

template <typename T>
T* address_of(T& t){return &t;}

std::transform(v.begin()+2, v.begin()+5, v_ref.begin(), address_of);
So if I use the code, as like you had posted, I do not need the
transform and the address_of (I really fear boost address_of ! )
Just can anyone say the pluses and minuses of the method ? In other way
is it the best possible way ? As you know now, I only need different
views (and sometimes hierarchical) of same data.

A lots of thanks for the answer
abir
Regards,
Ben

Ben
Nov 13 '06 #7

dasjotre wrote:
toton wrote:
benben wrote:
toton wrote:
Hi,
I am facing problem some times, and not finding a suitable answer to
solve it.
I have a vector (or some other container, sometimes) of some class,
named CC
like vector<CCv, NOT vector<CC*;

I want another class say Segment to refer a portion of this vector. I
can't store the iterator for vector as a member function to the class,
as
1) The iterators have different invalidation strategy, and may
invalidate the stored iterators when some new elements are added to the
vector.
2) The iterators are not default constructible, where I need to
calculate the range after Segment class is formed.
>
>
What's wrong with:
>
vector<CCv(10);
>
vector<CC*v_ref;
v_ref.push_back(&v[2]);
v_ref.push_back(&v[3]);
v_ref.push_back(&v[4]);
>
v_ref[0]->some_CC_memfun();
>
Notice that the all CC objects are owned by v. v_ref merely references
some of the elements assuming the pointers are valid within its
(v_ref's) life time.
Thanks. This is very much what I need.
But the questions are,
If v resizes (and increases) , and hence moves the elements whether
still v_ref will have a reference ? Is it true for any other container?
I know that instead of v_ref, If I store iterator begin_ = v.begin()+1
and, iterator end_ = v.begin()+3; they are no more valid when v
resizes, and increases size.

deque is closest to vector and may be implemented
the same.

Better solution is to use list or, if the problem
fits, ::boost::multi_index instead.
list is not a good option to me, as I need the frequent random access.
multi_index looks very promising. Will give it a look now, to check if
it fits my need.
And instead of manual pushback like this, is there a way to use std
copy algorithm which will copy the pointers ?

You can do that with transform and something like:

template<class T>
T * ptr_of(T & t){ return &t; }

template<class It1, class It2>
void transform_to_ptr(It1 begin, It1 end, It2 out)
{
::std::transform
( begin, end, out
, ::boost::bind( &ptr_of<typename It1::value_type>, _1)
);
}

void sampl()
{
::std::vector<intv;
::std::fill_n( ::std::back_inserter(v), 100, 10);

::std::vector<int*v1;
transform_to_ptr( v.begin(), v.end(), ::std::back_inserter(v1) );
}
Thanks for answering.
abir
Regards,
Ben
Nov 13 '06 #8

toton wrote:
list is not a good option to me, as I need the frequent random access.
multi_index looks very promising. Will give it a look now, to check if
it fits my need.
you will end up with some sort of 'binary' search

Nov 13 '06 #9

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

2
by: chris | last post by:
Hi there, I'd like to make a container div semi-transparent and its contents opaque. On the following page, the semi-transparency of the containing div is inherited by its children (whereas...
3
by: RubiconXing | last post by:
Hi All Beginner question - please be patient with me :-) I am new to c#. If one creates a child modal (and also non-modal) form what is the best way of returning the collected data back to the...
33
by: Jason Heyes | last post by:
I would like to modify the contents of a file, replacing all occurances of one string with another. I wrote these functions: bool read_file(std::string name, std::string &s); bool...
21
by: Mark Rae | last post by:
Hi, Apologies if this is a stupid question - I'm a C# newbie... :-) I have a Windows app with two form: frmConfigReg and frmNewApp. frmConfigReg is the startup form. It has several controls,...
19
by: JezB | last post by:
I have a DIV whose contents varies in size according to data. How can I size the DIV precisely to fit it's contents ?
1
by: VB Programmer | last post by:
With HTML, how do I get the value of a textbox in an ItemTemplate column within a datagrid? Simple shopping cart. For each row: 1 column is a textbox where they can enter the quantity. 1...
2
by: Celeste | last post by:
Hello, I'm trying to parse the referring url for google search terms so that when this page loads it will scroll to and highlight the search term(s). Should i be using document.referrer? ...
2
by: ge5talt | last post by:
Hi all, I am looking for a switch that will style the height of a parent element to a specific % if the height of the contents is less than the height of the container (it doesnt spill out), or...
14
by: jehugaleahsa | last post by:
I have a rather complex need. I have a class that parses web pages and extracts all relevant file addresses. It allows me to download every pdf on a web page, for instance. I would like to...
0
by: DolphinDB | last post by:
Tired of spending countless mintues downsampling your data? Look no further! In this article, you’ll learn how to efficiently downsample 6.48 billion high-frequency records to 61 million...
0
by: ryjfgjl | last post by:
ExcelToDatabase: batch import excel into database automatically...
1
isladogs
by: isladogs | last post by:
The next Access Europe meeting will be on Wednesday 6 Mar 2024 starting at 18:00 UK time (6PM UTC) and finishing at about 19:15 (7.15PM). In this month's session, we are pleased to welcome back...
0
by: Vimpel783 | last post by:
Hello! Guys, I found this code on the Internet, but I need to modify it a little. It works well, the problem is this: Data is sent from only one cell, in this case B5, but it is necessary that data...
0
by: ArrayDB | last post by:
The error message I've encountered is; ERROR:root:Error generating model response: exception: access violation writing 0x0000000000005140, which seems to be indicative of an access violation...
1
by: CloudSolutions | last post by:
Introduction: For many beginners and individual users, requiring a credit card and email registration may pose a barrier when starting to use cloud servers. However, some cloud server providers now...
1
by: Shællîpôpï 09 | last post by:
If u are using a keypad phone, how do u turn on JavaScript, to access features like WhatsApp, Facebook, Instagram....
0
by: af34tf | last post by:
Hi Guys, I have a domain whose name is BytesLimited.com, and I want to sell it. Does anyone know about platforms that allow me to list my domain in auction for free. Thank you
0
by: Faith0G | last post by:
I am starting a new it consulting business and it's been a while since I setup a new website. Is wordpress still the best web based software for hosting a 5 page website? The webpages will be...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.