|
Prev: Exceptions
Next: Pet peeves (lighthearted)
From: Martin Bonner on 6 Jul 2005 06:41 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 6 Jul 2005 09:26 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 6 Jul 2005 18:33 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 11 Jul 2005 02:58 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 22 Jul 2005 12:09
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! ] |