Template Problem

After a quick review of the board, I haven't found any questions like this.

Here's my dilemma:

I want to write a container class for a group of unique objects. I want to be able to add objects (without creating duplicates), remove objects, and see if an object is contained within the list. I also need to get constant iterators to the beginning and end of the list. Here's the prototype I have so far:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
  /// \brief Container class for a group of unique objects.
  template<class T, class List = std::list<T> >
  class Group {

  private:

    List object;		///< \brief Object list.

  public:

    /// \breif Returns a constant iterator to the beginning of the
    /// list.

    /// \return The iterator.
    List::const_iterator begin() const;

    /// \brief Returns a constant iterator to the end of the list.

    /// \return The iterator.
    List::const_iterator end() const;

    /// \brief Adds an object to the list.

    /// \param obj The object to add.

    /// \return Itself.
    Group &operator+=(const T &obj);

    /// \brief Removes an object from the list.

    /// \param obj Te object to remove.

    /// \return Itself.
    Group &operator-=(const T &obj);

    /// \brief Determines if an object is found in the list.

    /// \param obj The object to find.

    /// \return true if found, false otherwise.
    bool has(const T &obj) const;

  };


The begin() and end() functions refuse to compile because apparently List::const_iterator isn't valid. Can someone suggest an alternative?

Thanks.

P.S.: Please forgive the weird comments. They're interpreted by doxygen to automatically create my documentation for me.

P.P.S.: I've considered
template<class T, class List = std::list<T>, class Iter = std::list<T>::const_iterator>
but I'm hoping there's a cleaner way of changing the list type.
(EDIT: This apparently also isn't legal.)
Last edited on
isn't valid?
The error message I get is this:
1
2
life.hpp:45: error: type ‘List’ is not derived from type ‘life::Group<T, List>’
life.hpp:45: error: expected ‘;’ before ‘begin’


Line 45 corresponds to line 15 in the above code.

I get the same errors for line 20.

(EDIT: I'm using g++ (The GNU C++ compiler) not that it should make any difference.)
Last edited on
List::const_iterator
... is a dependent name, you have to write 'typename' before those.
IMHO, your class hasn't added anything to most STL container classes other than operator+= and operator-= as ways of inserting (push_back?) and removing instead of the methods provided by the container.

So I question the usefulness of this class in the first place. STL provides the find() algorithm which will work on all STL containers just as your has() method will. And begin() and end() are just forwarders of the underlying container's begin() and end() methods.
The difference is that the operator+= won't add a duplicate object.

If I were to write:
1
2
Group<int> foo;
foo += 3 += 3;

The resulting list would contain only one value since the second 3 would be discarded. If there is an STL container that does this, please let me know as I'll be happy to use that instead.
std::set

List::const_iterator
... is a dependent name, you have to write 'typename' before those.


Okay. Your solution works, but I'm not entirely certain why. Can you point me to somewhere that I can read up on this?

Also, why typename as opposed to class? Both seem to work.

(EDIT: Nevermind, I found my answer to both questions. Thanks for the help.)
Last edited on
The problem is an inherent ambiguity in the C++ grammar with respect to the scope resolution operator.

a::b::c

Could refer to namespace a, object b, type c. Or object a, type b, type c.
Or type a, type b, type c.

The compiler tries to make an intelligent guess, but it doesn't always get it right.
Using the keyword typename tells the compiler how to interpret it:

 
typedef typename List::const_iterator const_iterator;


resolves the ambiguity by telling the compiler that the expression "List::const_iterator" is a type.


You were right about std::set.

For some reason, I was of the impression that set was like map, only where Key and T were of the same class.

Thanks for the help. You've saved me a bunch of coding, even if I feel like a bit of an idiot now. ;)
Last edited on
Topic archived. No new replies allowed.