Templates and STL

The following code is a container based on std :: vector

template <typename Item>
struct TList
{
    typedef std::vector <Item> Type;
};


template <typename Item>
class List
{
private
            typename TList <Item>::Type items;
    ....
}

int main()
{
  List <Object> list;
}

Is it possible to templatize std :: vector and create a generic container, something like this?

template <typename Item, typename stl_container>
struct TList
{
    typedef stl_container<Item>;
};

where stl_container represents std :: vector, std :: list, std :: set ...? I would like to select the type of container at creation time.

List <Object, std::vector> list; //vector of objects, not a real code
List <Object, std::vector> list; //list of objects, not a real code

Thank you for your responses...

Updated question:

I tried the following code, but there are errors:

#include <vector>
template <typename Item, typename Container>
struct TList
{
   typedef typename Container <Item>::type type; //Error C2059: syntax error : '<', Error C2238: unexpected token(s) preceding ';
};


template <typename T>
struct vector_container
{
  typedef std::vector<T> type;
};

int _tmain(int argc, _TCHAR* argv[])
{
TList <int, vector_container> v;
TList <int, map_container> m;
}
+5
source share
6 answers

Yes, but not directly:

template <typename Item, template <typename> class Container>
struct TList
{
    typedef typename Container<Item>::type type;
};

Then you can define various container policies:

template <typename T>
struct vector_container
{
    typedef std::vector<T> type;
};

template <typename T>
struct map_container
{
    typedef std::map<T, std::string> type;
};

TList<int, vector_container> v;
TList<int, map_container> m;

A bit detailed. * To do something directly, you need to take the route described by James , but since he notes that it is ultimately very inflexible.

++ 0x :

#include <map>
#include <vector>

template <typename Item,
            template <typename...> class Container, typename... Args> 
struct TList
{
    // Args lets the user specify additional explicit template arguments
    Container<Item, Args...> storage;
};

int main()
{
    TList<int, std::vector> v;
    TList<int, std::map, float> m;
}

Perfect. , ++ 03, , .


* , " " " ". - , , . :

template <typename Item, typename Container = std::vector<Item>>
struct TList
{};

: , , Item, something_else<Item>? , - ? , , , , .

, , :

template <typename T>
struct allocator
{
    template <typename U>
    struct rebind
    {
        typedef allocator<U> type;
    };

    // ...
};

allocator<U> allocator<T>. ? ++ 0x :

template <typename T, typename Container>
struct rebind; // not defined

template <typename T, typename Container, typename... Args>
struct rebind<T, Container<Args...>>
{
    // assumes the rest are filled with defaults**
    typedef Container<T> type; 
};

std::vector<int>, , , rebind<float, std::vector<int>>::type. ++ 0x, ++ 03 .


** , , , , , , .., .:)

+11

, ( ) "".

, , , " " . , , ( ).

, std::stack (, std::deque, std::list std::vector) , std::stack / , . , std::stack, . :

namespace std {
    template <class T, class Container = deque<T> >
    class stack {
    public:
        typedef typename Container::value_type value_type;
        typedef typename Container::size_type  size_type;
        typedef Container                      container_type;
    protected:
        Container c;
    public:
        explicit stack(const Container& = Container());
        bool empty() const             { return c.empty(); }
        size_type size() const         { return c.size(); }
        value_type& top()              { return c.back(); }
        const value_type& top() const  { return c.back(); }
        void push(const value_type& x) { c.push_back(x); }
        void pop()                     { c.pop_back(); }
    };
}

, , - , , () .

+6

.

, ,

template <typename Item, template <typename> class Container>
struct TList { /* ... */ };

, , , . , std::vector, : . .

std::vector , TList :

template <typename Item, template <typename, typename> class Container>
struct TList { /* ... */ };

std::map , : , .

- .

+5

, :

template <typename T, typename stl_container = std::vector<T> >
struct TList
{
    typedef stl_container Type;
};

#define TLIST(T, C) TList<T, C<T> >

TList<int> foo;
TList<int, std::list<int> > bar;
TLIST(int, std::list) baz;
+2

templatize std::vector , - ?

. templatize - templatize .

. std::find:

template<class InputIterator, class T>
InputIterator find ( InputIterator first, InputIterator last, const T& value )
{
    for ( ;first!=last; first++) if ( *first==value ) break;
    return first;
}

, tempalte .

, , , , , Scott Meyers " STL" 2: .

0

, . , , , , , .

You can get around this by providing your own types of subclasses that accept the appropriate template parameters, and let any additions (which should have default values) be populated in my implementation:

template < typename T > struct simple_vector : std::vector<T> {};

Or you can use templated typedef idiom:

template < typename T > struct retrieve_vector { typedef std::vector<T> type; };
-1
source

All Articles