Thread: stl container as template argument

  1. #1
    Registered User
    Join Date
    Oct 2006
    Posts
    3,445

    stl container as template argument

    let's say I have a function like this:
    Code:
    template<typename ContainerT, typename ValueT>
    void foo(const ContainerT<ValueT>& c)
    {
      typedef ContainerT<ValueT> type;
      for (type::iterator it = c.begin(); it != c.end(); ++it)
      {
        // do some stuff
      }
    }
    and I would call it as follows:
    Code:
    std::vector<int> intVector;
    std::list<std::string> stringList;
    
    foo(intVector);
    foo(stringList);
    obviously this will not compile, because the compiler has no way of knowing that ContainerT is a template type.

    is there any way to make something like this work?

  2. #2
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Make it

    Code:
    template<typename ContainerT>
    void foo(const ContainerT& c)
    Now, typical containers expose public typedefs within that you can grab for the value type, etc.
    I believe typename ContainerT::value_type should do the trick for replacing ValueT.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  3. #3
    Registered User
    Join Date
    Oct 2006
    Posts
    3,445
    yes, that will work with standard containers, but I was hoping there was a way to separate the container from its value type in the template parameters, for other potential uses. I can foresee a situation where the parameter would be something other than a container, and the function would do something other than iterate, and you would need to know what ValueT is, without depending on a specific interface.

  4. #4
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    If you want that, then you will have to make an extra layer of redirection. There is a way to detect if there is a typedef of a specific type or not and depending on that fact, take an action.
    You should make sure that your containers contain a value_type typedef to make it work with this function, too.

    Unfortunately, standard containers take an undefined amount of template parameters, making this approach tricky. You might be able to pull it off using varadic templates, though.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  5. #5
    Officially An Architect brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,396
    Fundamentally the trouble stems from putting the ContainerT type into the equation in the first place. Move the iterators OUTSIDE this function, forcing the caller to pass the beginning and ending iterators explicitly instead of obtaining them within your template. Not only do you gain freedom from needing to know the container type, you gain the ability to support things that don't have begin() and end() functions, and things which aren't even classes at all (like bare pointers).

    In fact I'd just chuck the whole thing and use std::for_each.
    Code:
    //try
    //{
    	if (a) do { f( b); } while(1);
    	else   do { f(!b); } while(1);
    //}

  6. #6
    Algorithm Dissector iMalc's Avatar
    Join Date
    Dec 2005
    Location
    New Zealand
    Posts
    6,318
    It's possible that you want a templated template type:
    Code:
    template<template <class> class ContainerT, class ValueT>
    Yes that's valid syntax, I use essentially that in my policy based renderer.
    My homepage
    Advice: Take only as directed - If symptoms persist, please see your debugger

    Linus Torvalds: "But it clearly is the only right way. The fact that everybody else does it some other way only means that they are wrong"

  7. #7
    Registered User
    Join Date
    Oct 2006
    Posts
    3,445
    Quote Originally Posted by iMalc View Post
    Code:
    template<template <class> class ContainerT, class ValueT>
    that seems to work ok, but when I replace the keyword "class" with "typename" I get the error "expected 'class' before 'ContainerT'

    I'm using G++ 4.6.1 on Fedora 15. is this a bug in G++, or is it actually mandatory to use "class" in this case? I've had situations where the reverse was not allowed, but I've never seen a case where you couldn't use the "typename" keyword in place of "class."

  8. #8
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    As expected, this does not compile properly:

    Code:
    #include <vector>
    
    template<template<typename> class ContainerT, typename ValueT>
    void foo(const ContainerT<ValueT>& c)
    {
      typedef ContainerT<ValueT> type;
      for (typename type::iterator it = c.begin(); it != c.end(); ++it)
      {
        // do some stuff
      }
    }
    
    int main() { std::vector<int> v; foo(v); }
    (Btw, you forgot the red part.)

    I was able to get it to compile with the following:
    Code:
    #include <vector>
    
    template<template<typename, typename> class ContainerT, typename ValueT>
    void foo(const ContainerT<ValueT, std::allocator<ValueT>>& c)
    {
      typedef ContainerT<ValueT, std::allocator<ValueT>> type;
      for (auto it = c.begin(); it != c.end(); ++it)
      {
        // do some stuff
      }
    }
    
    
    int main() { std::vector<int> v; foo(v); }
    But this just shows how unreliable this method is, and how it should not be used.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  9. #9
    Registered User
    Join Date
    Oct 2006
    Posts
    3,445
    I've decided to abandon my research into this. it may be possible, but the work involved to make a portable, universal solution appears to be quite unreasonable.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Template Argument inside the Argument of a Function Declaration
    By manasij7479 in forum C++ Programming
    Replies: 3
    Last Post: 06-11-2011, 05:53 AM
  2. Thoughts on return type from template container classes.
    By Subsonics in forum C++ Programming
    Replies: 17
    Last Post: 10-17-2010, 03:10 AM
  3. template argument
    By George2 in forum C++ Programming
    Replies: 4
    Last Post: 03-12-2008, 03:01 AM
  4. Template function as argument
    By xErath in forum C++ Programming
    Replies: 9
    Last Post: 10-03-2004, 09:38 PM
  5. Replies: 4
    Last Post: 03-21-2004, 03:34 PM