From: Martin Bonner on
Mark Van Peteghem wrote:
> Ithier wrote:
>
> >Hi,
> >
> >I need a special container which does not exist, I think. It's a kind of
> >list and set. It's a set because each included object has to be unique
> >and it's a kind of list because the order has to be kept as is.
> >For example, if I insert objects A, Z, B, Z, A and C, I need to store
> >only A, Z, B, C, in that order.
> >
> >To achieve this I have three solutions:
> >1ý) Create a new container type, with all the caracteristic needed. The
> >objects will be stored inside my mew container in a vector or list.
> >2ý) Write a special inserter to achieve the desired goal (an inserter
> >function object) which will check that an entry doesn't exist before
> >inserting it really.
> >3ý) Write an algorithm that will remove the duplicate entries (as the
> >std::unique function do, unfortunatly it works only on sorted containers).

> Why do you still need this if step 2 already checks if the element
> is already in the container? Steps 1 and 2 seem sufficient for what
> you want to do.

These aren't steps. They are disjoint solutions. If the container
handles it, you don't need a special inserter; if you have a
super_unique algorithm, you don't need a special container.


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: Maciej Sobczak on
Carlos Moreno wrote:

>>template <class Container, typename Value>
>>void add_unique(Container &c, Value const &v)
>
> Was that intentional?

Yes, my keyboard gives me an unpleasant electric shock when I try to
write it differently. ;)

> If so, may I ask why the choice of "class"
> for the first type parameter and typename for the second?

Some time ago I've seen a guideline explaining the difference (but I
forgot where it comes from, so I cannot give references).
It boils down to the following:

- Write "typename" if the actual parameter can be anything (not counting
other constraints that apply anyway, like copyability, being a random
access iterator, etc.), including fundamental types. Above, Value can be
anything, even a char or bool.

- Write "class" if the actual parameter cannot be a fundamental type.
Above, Container certainly must be a user-defined type.


There is no other purpose behind it than being a comment. Of course, it
has no meaning to the compiler.


--
Maciej Sobczak : http://www.msobczak.com/
Programming : http://www.msobczak.com/prog/

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: Carlos Moreno on
Maciej Sobczak wrote:

>>>template <class Container, typename Value>
>>>void add_unique(Container &c, Value const &v)
>>
>>Was that intentional?
>
> Yes, my keyboard gives me an unpleasant electric shock when I try to
> write it differently. ;)

Hmmm, I wonder if your monitor would send an electric shock straight
to the face by merely reading it differently... ;-) (yeah, I know,
you're going to tell me that you have an LCD and thus it is incapable
of sending an electric shock :-))

Hmmm, I'm tempted to try by writing it right here and wait for your
response, but I don't want to risk innocent bystanders getting a shock
for no good reason other than getting caught in our cross-fire... ;-)

> There is no other purpose behind it than being a comment. Of course, it
> has no meaning to the compiler.

That's what I thought... I kind of like the convention, but I think
it may be too late for me to adopt it (I've stuck to the "typename"
convention for too long :-)).

OTOH, as a counter-argument to it: using class to "document" that
detail is kind of redundant -- the name of the type parameter
(Container) does reflect that (*) and more (it not only says that
it can't be a built-in type and must be a class: it also says that
it is supposed to be a certain type of class)

(*) at least it should reflect that -- coming from you, I would
expect no less than a properly chosen name for it


Cheers,

Carlos
--

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: Tokyo Tomy on
Ithier <nospam(a)nospam.com> wrote in message news:<dadatd$31a$1(a)reader1.imaginet.fr>...
> Hi,
>
> I need a special container which does not exist, I think. It's a kind of
> list and set. It's a set because each included object has to be unique
> and it's a kind of list because the order has to be kept as is.
> For example, if I insert objects A, Z, B, Z, A and C, I need to store
> only A, Z, B, C, in that order.
>
[snip]

Why don't you combine the two ideas: one from Richard Corden and one
from Maciej Sobczak.

Sobczak uses the std::find as equality tester, but let me use std::set
as equality tester, as proposed by Corden. I expect std::set will be
faster than std:find to carry out the test in the case that there are
many elements, because std::set make a binary search, while std::find
make a linear search.

This time, as add_unique should have an internal state, the algorithm
function should be a fanctor. However let me show a code for "thin
wrapper" as proposed by Dave Harris, although I did not stop any
functionalities of vector or list (Maybe,I should have stopped some
functionalities.)

I think the OP is satisfied with the Sobczak proposal, but if you
anticipate the increase of the elements in future, please think about
the proposal here.


//[code]
#include <vector>
#include <set>
#include <list>
#include <iostream>

template<typename continerT>
class singular_continer: public continerT {
public:
void add_unique(typename continerT::value_type x);

private:
std::set<typename continerT::value_type> s;
};

template<typename continerT>
void singular_continer<continerT>::add_unique(typename
continerT::value_type x)
{
if(s.insert(x).second == true) push_back(x);
}

int main()
{
singular_continer<std::vector<char> > c;

c.add_unique('A');
c.add_unique('Z');
c.add_unique('B');
c.add_unique('Z');
c.add_unique('A');
c.add_unique('C');

assert(c.size() == 4);
assert(c[0] == 'A');
assert(c[1] == 'Z');
assert(c[2] == 'B');
assert(c[3] == 'C');

singular_continer<std::list<char> > l;

l.add_unique('A');
l.add_unique('Z');
l.add_unique('B');
l.add_unique('Z');
l.add_unique('A');
l.add_unique('C');

for ( singular_continer<std::list<char> >::iterator it =
l.begin(); it ! l.end(); ++it)
std::cout << *it << " " ;

std::cout << std::endl;

for( std::list<char>::iterator it = l.begin(); it != l.end();
++it)
std::cout << *it << " " ;


return 0;

}

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: Ben Hutchings on
Maciej Sobczak <no.spam(a)no.spam.com> wrote:
> Carlos Moreno wrote:
>
>>>template <class Container, typename Value>
>>>void add_unique(Container &c, Value const &v)
>>
>> Was that intentional?
>
> Yes, my keyboard gives me an unpleasant electric shock when I try to
> write it differently. ;)
>
>> If so, may I ask why the choice of "class"
>> for the first type parameter and typename for the second?
>
> Some time ago I've seen a guideline explaining the difference (but I
> forgot where it comes from, so I cannot give references).
<snip>

Andrei Alexandrescu uses this convention and described it in
Modern C++ Design.

--
Ben Hutchings
Having problems with C++ templates? Your questions may be answered by
<http://womble.decadentplace.org.uk/c++/template-faq.html>.

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

First  |  Prev  |  Next  |  Last
Pages: 1 2 3 4
Prev: Exceptions
Next: Pet peeves (lighthearted)