Simple template issue

Collapse
X
 
  • Time
  • Show
Clear All
new posts
  • nbransby
    New Member
    • Mar 2008
    • 3

    Simple template issue

    Why does...

    class Foo
    {
    std::list<int> list;
    std::map<int, std::list<int>: :iterator> map;
    };

    ...compile, while this...

    template<class T> class Foo
    {
    std::list<T> list;
    std::map<int, std::list<T>::i terator> map;
    };

    ...fails with...

    /foo.h:129: error: type/value mismatch at argument 2 in template parameter list for ‘template<class _Key, class _Tp, class _Compare, class _Alloc> class std::map’
    /foo.h:129: error: expected a type, got ‘std::list<T*,s td::allocator<T *> >::iterator’
    /foo.h:129: error: template argument 4 is invalid

    ...i thought templates of templates were fine?

    Thanks

    Nick
  • weaknessforcats
    Recognized Expert Expert
    • Mar 2007
    • 9214

    #2
    Originally posted by nbransby
    std::map<int, std::list<T>::i terator> map;
    The map contains pair<> objects. The pair has a type for the first and the second member. std::list<T>::i terator is not a type so it won't compile. std::list<int>: :iterator is a type so that's OK.

    This is due to the fact that std::list::iter ator is a nested class within list. To get the iterator type you have to know the type of the list.

    Now if you just don't use an iterator but have the map contain a list<T>, then it will compile OK:

    [code=cpp]
    template<class T> class Foo
    {
    std::list<T> listobj;
    std::map<int, std::list<T> > mapobj;
    };
    [/code]

    Note that I changed the names of your objects so they are not the same as the template name.

    Comment

    • nbransby
      New Member
      • Mar 2008
      • 3

      #3
      Originally posted by weaknessforcats
      The map contains pair<> objects. The pair has a type for the first and the second member. std::list<T>::i terator is not a type so it won't compile. std::list<int>: :iterator is a type so that's OK.

      This is due to the fact that std::list::iter ator is a nested class within list. To get the iterator type you have to know the type of the list.
      I thought the complier would delay compilation until it found a statement providing the type of the list, such as

      [code=cpp]Foo<int> foo;[/code]
      From this the complier can deduce that its a map of int list iterators im after (the type std::list<int>: :iterator). I still don't see why this is not possible.

      Originally posted by weaknessforcats
      Now if you just don't use an iterator but have the map contain a list<T>, then it will compile OK:

      [code=cpp]
      template<class T> class Foo
      {
      std::list<T> listobj;
      std::map<int, std::list<T> > mapobj;
      };
      [/code]

      Note that I changed the names of your objects so they are not the same as the template name.
      But I dont want map of lists, I want a map of list iterators. What I am trying to doing here is map the nodes of the list so I can quickly lookup a node and remove from the list (without having to iterate the list)

      Comment

      • baudolino
        New Member
        • Sep 2007
        • 6

        #4
        Use "typename" keyword (clarifies that an identifier inside a template is a type)

        std::map<int, typename std::list<T>::i terator> map;

        Comment

        • weaknessforcats
          Recognized Expert Expert
          • Mar 2007
          • 9214

          #5
          This works:
          [code=cpp]
          template<class T>
          void fx()
          {
          std::list<T>::i terator itr;
          std::map<T, std::list<T>::i terator> theMap;
          };
          int main()
          {
          fx<int>();
          }
          [/code]

          Here you have a function template that defines a map of iterators.

          However, when you do this in a class:
          [code=cpp]
          template<class T>
          class fx
          {
          std::list<T>::i terator itr;
          std::map<T, std::list<T>::i terator> theMap;
          };
          int main()
          {
          fx<int> obj;
          }
          [/code]

          you get errors that std::list<T> is not a type. What happens here is that the compiler is not sure if std::list<T>::i terator is a type or whether it should make a copy of the std::list::iter ator template, plug in the T and create an instance of the template. Because of that ambiguity, whenever you have this situation, referred to as a dependent type, you have to tell the compile that list<T> is a type.

          So you do this:
          [code=cpp]
          template<class T>
          class fx
          {
          typename std::list<T>::i terator itr;
          typename std::map<T, typename std::list<T>::i terator> theMap;
          };
          int main()
          {
          fx<int> obj;
          }
          [/code]

          and everything should compile.

          Comment

          • nbransby
            New Member
            • Mar 2008
            • 3

            #6
            thanks you it compiles now

            Comment

            Working...