Search code examples
c++templatesstlc++14template-templates

A template that contains std collection iterators


This template is able to store vector iterator(s) of a specific type.

template<typename T>
struct foo
{
  typedef typename std::vector<T>::iterator it;

  std::vector<it> m_collection;
};

How can template be made more generic and support other std collection iterators (std::list, std::deque etc)?


Solution

  • How can template be made more generic and support other std collection iterators (list, deque etc)?

    Do you want to pass the containers as template arguments?

    That is: are you looking for template-template arguments?

    template <template <typename...> class C, typename T>
    struct foo
    {
      typedef typename C<T>::iterator it;
    
      std::vector<it> m_collection;
    };
    

    Usable as follows

    foo<std::vector, int>  fvi;
    foo<std::set, long>    fsl;
    

    Or maybe

    template <template <typename...> class C, typename ... Ts>
    struct foo
    {
      typedef typename C<Ts...>::iterator it;
    
      std::vector<it> m_collection;
    };
    

    So you can use it also for maps ?

    foo<std::map, int, std::string>      fmis;
    foo<std::unordered_map, long, char>  fulc;
    

    Unfortunately this solution is incompatible with std::array, that require a not-template argument.

    Or maybe you want to pass the type and select container and contained type as through specialization?

    template <typename>
    struct foo;
    
    template <template <typename...> class C, typename ... Ts>
    struct foo<C<Ts...>>
    {
      typedef typename C<Ts...>::iterator it;
    
      std::vector<it> m_collection;
    };
    

    So you can use it as follows

    foo<std::vector<int>>                fvi;
    foo<std::set<long>>                  fsl;
    foo<std::map<int, std::string>>      fmis;
    foo<std::unordered_map<long, char>>  fulc;
    

    and also add a specialization for std::array

    template <template <typename, std::size_t> class A,
              typename T, std::size_t N>
    struct foo<A<T, N>>
    {
      typedef typename A<T, N>::iterator it;
    
      std::vector<it> m_collection;
    };
    

    Or, maybe, simply

    template <typename T>
    struct foo
    {
      typedef typename T::iterator it;
    
      std::vector<it> m_collection;
    };
    

    without deducing container and contained type?