Should I be using something other than raw pointers as a helper indexinto a collection?

K

K. Frank

Hello Group!

I have a collection.

(It happens to be an unordered_map, hence my earlier question
about possible pointer invalidation, but for the purposes of
this question it could be a map or set, etc.)

In addition to element access through the built-in features
of the collection class, I also want quick access to the first
few elements according to some independent sorting criterion.

Therefore my wrapper class contains not only the underlying
collection, but a helper index that is a (sorted) set of
pointers to values in the collection. I am using raw pointers
for this, basically because I don't see any need to use some
sort of smart pointer.

I do know the various smart pointers have been getting better
designed over the years and are now part of the standard.

Is there a good reason I should be using some sort of smart
pointer? Is there a compelling reason?

Some details: In my particular use case, items are never
removed form the main collection. If they were, of course,
my wrapper class would need to keep the helper index in
sync by also removing the corresponding index -- just as
it keeps the helper index in sync when items are added.
Also, the helper index is used only to access the items,
not to modify or remove them.

Thanks for an smart-pointer wisdom.


K. Frank
 
G

Gerhard Fiedler

K. Frank said:
Hello Group!

I have a collection.

(It happens to be an unordered_map, hence my earlier question
about possible pointer invalidation, but for the purposes of
this question it could be a map or set, etc.)

In addition to element access through the built-in features
of the collection class, I also want quick access to the first
few elements according to some independent sorting criterion.

Therefore my wrapper class contains not only the underlying
collection, but a helper index that is a (sorted) set of
pointers to values in the collection. I am using raw pointers
for this, basically because I don't see any need to use some
sort of smart pointer.

I do know the various smart pointers have been getting better
designed over the years and are now part of the standard.

Is there a good reason I should be using some sort of smart
pointer? Is there a compelling reason?

Some details: In my particular use case, items are never
removed form the main collection. If they were, of course,
my wrapper class would need to keep the helper index in
sync by also removing the corresponding index -- just as
it keeps the helper index in sync when items are added.
Also, the helper index is used only to access the items,
not to modify or remove them.

Thanks for an smart-pointer wisdom.

The main use of smart pointers is for (automatic) lifetime management of
the pointee. In your case, the lifetime is managed by your main
collection, so there is no need to use smart pointers in your index
collection.

Gerhard
 
K

K. Frank

Hi Gerhard!

The main use of smart pointers is for (automatic) lifetime management of
the pointee. In your case, the lifetime is managed by your main
collection, so there is no need to use smart pointers in your index
collection.

Thank you. That agrees with my basic thinking, although I wouldn't
have been able to express it as cleanly as you did.

Best.


K. Frank
 
Ö

Öö Tiib

I have a collection.

(It happens to be an unordered_map, hence my earlier question
about possible pointer invalidation, but for the purposes of
this question it could be a map or set, etc.)

In addition to element access through the built-in features
of the collection class, I also want quick access to the first
few elements according to some independent sorting criterion.

Therefore my wrapper class contains not only the underlying
collection, but a helper index that is a (sorted) set of
pointers to values in the collection. I am using raw pointers
for this, basically because I don't see any need to use some
sort of smart pointer.

I do know the various smart pointers have been getting better
designed over the years and are now part of the standard.

Is there a good reason I should be using some sort of smart
pointer? Is there a compelling reason?

Some details: In my particular use case, items are never
removed form the main collection. If they were, of course,
my wrapper class would need to keep the helper index in
sync by also removing the corresponding index -- just as
it keeps the helper index in sync when items are added.
Also, the helper index is used only to access the items,
not to modify or remove them.

You might be interested in Boost.Multi-index. Or not. See:

http://www.boost.org/doc/libs/1_53_0/libs/multi_index/doc/index.html

It is the sort of thing that one may actually need when simple sets
and maps are not enough. It all depends what you do with it.
 
K

K. Frank

Hi Öö!

You might be interested in Boost.Multi-index. Or not. See:

http://www.boost.org/doc/libs/1_53_0/libs/multi_index/doc/index.html

It is the sort of thing that one may actually need when simple sets
and maps are not enough. It all depends what you do with it.

Yes, this is a very good recommendation. I've looked at
Boost.MultiIndex
for this use case. It looks like what I'm doing is a baby version of
the more full-featured functionality that Boost.MultiIndex provides.

However (unlike many participants in this group) I tend to stay away
from boost as it is large and unwieldy. I generally avoid large and
unwieldy packages unless they offer nearly irreplaceable
functionality.
(For example, I do invest the time and effort in building and
upgrading
Qt, a GUI / application framework. Qt is large and unwieldy, but if
you want to program GUI's, you need something like Qt.)

For example, boost offers various smart pointers (now subsumed, I
suppose,
into C++11). But the idea that I should download and deal with the
boost state-machine framework or spirit parser generator (both
implemented
with template meta-programming, if I'm not mistaken), just to get
smart
pointers, seems excessive to me. The notion that I should download
the
whole boost ball of wax, and then run various third-party scripts on
it to strip away all of the unneeded non-dependencies, just to get a
clean set of smart pointers -- well, I just don't get it.

But I'd love to learn more about Boost.MultiIndex -- it seems like a
good idea.

Thanks.


K. Frank
 
Ö

Öö Tiib

Yes, this is a very good recommendation. I've looked at
Boost.MultiIndex
for this use case. It looks like what I'm doing is a baby version of
the more full-featured functionality that Boost.MultiIndex provides.

However (unlike many participants in this group) I tend to stay away
from boost as it is large and unwieldy. I generally avoid large and
unwieldy packages unless they offer nearly irreplaceable
functionality.

Boost is collection of libraries. There are lot of libraries. Like
hundred. The libraries are designed by different people and usually
rather weakly related with each other. The people are usually known
as good specialists. So what you get is a big pile of libraries
written by good specialists with one download.
(For example, I do invest the time and effort in building and
upgrading
Qt, a GUI / application framework. Qt is large and unwieldy, but if
you want to program GUI's, you need something like Qt.)

Yes, Qt is application framework. That is designed by one company and
it is quite heavily interrelated with other parts of itself. I also
use it sometimes to throw up quick prototype or a GUI for some tool.
For example, boost offers various smart pointers (now subsumed, I
suppose,
into C++11). But the idea that I should download and deal with the
boost state-machine framework or spirit parser generator (both
implemented
with template meta-programming, if I'm not mistaken), just to get
smart
pointers, seems excessive to me.

You do not have to deal with all the libraries. Actually I have only
once looked into several of them and others I have never looked into.
Neither the performance nor usability nor maintainability of boost
libraries is guaranteed to be best but it is often better than same
thing reinvented by average Joe.

I haven't measured, but lets say whole boost with everything built and
ready takes 10Gb. 10Gb of hard-drive space costs less than 1 euro. The
built executable that uses something from boost is about as large as
built executable that does same thing without using anything from boost.
The notion that I should download the
whole boost ball of wax, and then run various third-party scripts on
it to strip away all of the unneeded non-dependencies, just to get a
clean set of smart pointers -- well, I just don't get it.

Most of boost is header-only. That means if you do not #include it
then you do not use it. Most of boost are templates. That means if
you do not instantiate a template in your code then compiler generates
nothing into your program. You only get what you use.
But I'd love to learn more about Boost.MultiIndex -- it seems like a
good idea.

It can be too generic at first to get the thing declared. Once done
it just works, like any other container.
 
J

James Kanze

I have a collection.
(It happens to be an unordered_map, hence my earlier question
about possible pointer invalidation, but for the purposes of
this question it could be a map or set, etc.)
In addition to element access through the built-in features
of the collection class, I also want quick access to the first
few elements according to some independent sorting criterion.
Therefore my wrapper class contains not only the underlying
collection, but a helper index that is a (sorted) set of
pointers to values in the collection. I am using raw pointers
for this, basically because I don't see any need to use some
sort of smart pointer.
I do know the various smart pointers have been getting better
designed over the years and are now part of the standard.

I'm not sure that I'd agree with that statement. Of all of the
smart pointers I've used (or tried to use), std::shared_ptr
probably has the worst design of them all.
Is there a good reason I should be using some sort of smart
pointer? Is there a compelling reason?
Some details: In my particular use case, items are never
removed form the main collection. If they were, of course,
my wrapper class would need to keep the helper index in
sync by also removing the corresponding index -- just as
it keeps the helper index in sync when items are added.
Also, the helper index is used only to access the items,
not to modify or remove them.

I don't see why anyone would want a smart pointer anywhere here.
If the items are never removed from the main container, using
smart pointers there is just introducing unnecessary
complication. And using them in the secondary indexes would
even be considered obfuscation---you're suggesting something
about the secondary indexes which isn't true.
 
B

Balog Pal

Is there a good reason I should be using some sort of smart
pointer?

In theory, sure. You use smart pointer for being smart. Because you
expect the very feature it is smart on. Because it aligns with your demand.
Is there a compelling reason?

That is up to you to decide. What smart behavior do you expect for the
use case? Make a list. Them match it against the supply.

If your list is empty to start with, the plain pointer is as smart as it
gets.
 
K

K. Frank

Hello James (and Balog)!

I'm not sure that I'd agree with that statement.  Of all of the
smart pointers I've used (or tried to use), std::shared_ptr
probably has the worst design of them all.

Thank you for the heads-up on that.
I don't see why anyone would want a smart pointer anywhere here.
If the items are never removed from the main container, using
smart pointers there is just introducing unnecessary
complication.  And using them in the secondary indexes would
even be considered obfuscation---you're suggesting something
about the secondary indexes which isn't true.

That was pretty much my conclusion, as well.

I think, in Balog's wording, my "list is empty."

The reason I posted the question in the first place is that I
haven't used smart pointers much in the past, and I have yet
to use a c++11 smart pointer. Nonetheless, one sees a lot of
commentary advocating the use of smart pointers (where appropriate,
of course), and since I don't have a deep understanding of the
use cases for c++11 (and other) smart pointers, I wanted to make
sure I wasn't missing anything.
...
James

Thanks for your advice.


K. Frank
 
W

woodbrian77

I haven't measured, but lets say whole boost with everything built and
ready takes 10Gb. 10Gb of hard-drive space costs less than 1 euro. The
built executable that uses something from boost is about as large as
built executable that does same thing without using anything from boost.

There are differences in the size of executables --
http://webEbenezer.net/comparison.html
One time the Boost version is 2.6 times larger and
another time it's 4 times larger than Ebenezer versions.

I think it makes sense to "chew the meat and spit the
bones" with Boost. Some of the libraries are excellent,
but not all of them. The intrusive containers
library and some of the other containers in Boost
are examples of what I think are great libraries.

Brian
Ebenezer Enterprises - John 3:16.
http://webEbenezer.net
 
Ö

Öö Tiib

There are differences in the size of executables --
http://webEbenezer.net/comparison.html
One time the Boost version is 2.6 times larger and
another time it's 4 times larger than Ebenezer versions.

Probably that boost serialize does more than than your software.
Can the Ebenezer serialize that Boost.MultiIndex that I suggested
to OP? As XML? Actually I dislike Boost.Serialize since it feels
complicated.
I think it makes sense to "chew the meat and spit the
bones" with Boost. Some of the libraries are excellent,
but not all of them. The intrusive containers
library and some of the other containers in Boost
are examples of what I think are great libraries.

When I feel that I do not understand how it does what it
does then I avoid using it. I generally avoid using source
code that appears too complex for me to maintain.
Performance is of secondary importance. If I can
maintain it then I can profile it too if needed.
 
W

woodbrian77

Probably that boost serialize does more than than your software.
Can the Ebenezer serialize that Boost.MultiIndex that I suggested
to OP? As XML?

"Yes" to the first question and "no" to the second.

Actually I dislike Boost.Serialize since it feels
complicated.

Sometimes I think that an advantage to on line code
generation, an unusual approach in 2002, is that
people have been slow to jump on the bandwagon. I
would have liked to have more users, but on the other
hand it makes it easier to make interface breaking
changes while there aren't many that are affected.
A lot has been learned about interface design over
the past ten years so I hope we're able to incorpor-
ate more of that sooner than later.
When I feel that I do not understand how it does what it
does then I avoid using it. I generally avoid using source
code that appears too complex for me to maintain.
Performance is of secondary importance. If I can
maintain it then I can profile it too if needed.

The compression library I use is only 991 lines, but I
don't understand much of it. Probably it would take me
weeks to get some idea of how it works. I'd communicate
with the author though if there is a problem with the
library. He's answered some questions I've had so
hopefully he'll be available if there's a problem with it.


Brian
Ebenezer Enterprises - So far G-d has helped us.
http://webEbenezer.net
 
Ö

Öö Tiib

The compression library I use is only 991 lines, but I
don't understand much of it. Probably it would take me
weeks to get some idea of how it works. I'd communicate
with the author though if there is a problem with the
library. He's answered some questions I've had so
hopefully he'll be available if there's a problem with it.

Sure, perhaps my view of things is because I just like to
understand complex algorithms. Be it compression or linear algebra I
am not happy when using it without feel that I will understand it
if needed. It is written by a human like me and so it certainly
contains defects. Take for example binary search. It is so simple?

Jon Bentley: "While the first binary search was published in 1946,
the first binary search that works correctly for all
values of n did not appear until 1962."
http://googleresearch.blogspot.com/2006/06/extra-extra-read-all-about-it-nearly.html

I do not like needless complexity that is caused by usage of
unsuitable tools. C++ template meta-programming was not designed
into language and so it usually looks like the hack it is. Your
idea to generate code is lot better at the moment.
 
J

James Kanze

Hello James (and Balog)!
The reason I posted the question in the first place is that I
haven't used smart pointers much in the past, and I have yet
to use a c++11 smart pointer. Nonetheless, one sees a lot of
commentary advocating the use of smart pointers (where appropriate,
of course), and since I don't have a deep understanding of the
use cases for c++11 (and other) smart pointers, I wanted to make
sure I wasn't missing anything.

Smart pointers are the current silver bullet. It's a lot easier
for commentators to recommend using a smart pointer everywhere
than for them to recommend actually doing some design. There
are places where smart pointers are an appropriate solution; my
first smart pointers go back some twenty years or more. But
there is no silver bullet, and I've found very few, if any cases
where smart pointers were appropriate in a container.
 
W

woodbrian77

"Yes" to the first question and "no" to the second.

There are some limitations on our support of multi_index_container:
1. At most one sequenced index.
2. If a sequenced index is used, it must be the
first index listed in the "IndexSpecifierList."
3. Transmission of a multi_index_container will probably not
preserve the relative order of elements that are
considered equal under an ordered_non_unique index.


These limitations permit a process which uses a
multi_index_container to serialize it's data and
then be used in another process that is using a
"single index container" like vector or deque.

I guess the first and third limitations are what are
needed for that. The second one is due to an
implementation difficulty.


Brian
Ebenezer Enterprises
http://webEbenezer.net
 
L

Luca Risolia

K. Frank said:
Hello Group!

I have a collection.

(It happens to be an unordered_map, hence my earlier question
about possible pointer invalidation, but for the purposes of
this question it could be a map or set, etc.)

In addition to element access through the built-in features
of the collection class, I also want quick access to the first
few elements according to some independent sorting criterion.

Therefore my wrapper class contains not only the underlying
collection, but a helper index that is a (sorted) set of
pointers to values in the collection. I am using raw pointers
for this, basically because I don't see any need to use some
sort of smart pointer.

Reference wrappers might be a convenient alternative to raw pointers.

For example:

using namespace std;

unordered_map<int, int> m{{3, 1}, {2, 2}, {1, 3}};
vector<reference_wrapper<decltype(m)::value_type>> v{begin(m), end(m)};
sort(begin(v), end(v), less<decltype(m)::value_type>{});
 
B

Balog Pal

Reference wrappers might be a convenient alternative to raw pointers.

For example:

using namespace std;

unordered_map<int, int> m{{3, 1}, {2, 2}, {1, 3}};
vector<reference_wrapper<decltype(m)::value_type>> v{begin(m), end(m)};

Hm, is it worth?
sort(begin(v), end(v), less<decltype(m)::value_type>{});

I have a small suite of function adapters for that case from the old
times. Nowadays we have lambda for solo cases too.
 
J

Jorgen Grahn

....
It is true that it is large but this only affects the initial download
time.

It depends on your environment. (Parts of) Boost is a standard part
of Debian Linux, and there it's split into >20 packages.

/Jorgen
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,537
Members
45,020
Latest member
GenesisGai

Latest Threads

Top