C++中的模板化地图/多图功能

Ken*_*ams 3 c++ templates

假设我有:

std::map<K, V1> m1;
std::multimap<K, V2> m2;
Run Code Online (Sandbox Code Playgroud)

我想按容器类型和键/值类型模板.但是以下不起作用:/

template <typename T>
void do_something(T var)
{
  // do something
}

template <typename TContainer, typename TKey, typename TVal>
void func(const TContainer<TKey, TVal>& container)
{
  for (typename TContainer<TKey, TVal>::iterator it = container.begin(); it != container.end(); ++it)
  {
    do_something(it->second);
  }
}
Run Code Online (Sandbox Code Playgroud)

然后调用它:

func(m1);
func(m2);
Run Code Online (Sandbox Code Playgroud)

Luc*_*lle 7

你不能只有一个模板参数吗?

template <typename Container>
void func(const Container & container)
{
    for (typename Container::iterator it = container.begin(); it != container.end(); ++it)
    {
        do_something(it->second);
    }
}
Run Code Online (Sandbox Code Playgroud)

或者更好的是,将迭代器传递给函数而不是容器:

template <typename ForwardIterator>
void func(ForwardIterator begin, ForwardIterator end)
{
    for (; begin != end; ++begin)
    {
        do_something(begin->second);
    }
}
Run Code Online (Sandbox Code Playgroud)

如果您真的需要模板模板参数,请参考以下语法:

template <template <typename, typename> Container, typename TKey, typename TValue>
void func(const Container<TKey, TValue> & container);
Run Code Online (Sandbox Code Playgroud)

但是,这对STL容器不起作用,因为它们通常具有比看起来更多的参数; 实际上,它们通常具有默认值的参数,例如allocator,所以最好的办法是使用上面描述的通用算法的惯用方法,即处理迭代器而不是容器.


sbi*_*sbi 7

这不起作用的原因是std::map需要四个模板参数:

template<class Key,
         class Value,
         class Predicate = std::less<Key>,
         class Allocator = std::allocator<pair<const Key, Value> > >
class map;
Run Code Online (Sandbox Code Playgroud)

虽然您可以省略最后两个用于实例化的参数,但您必须列出它们才能使模板匹配起作用:

template < typename TKey, 
           typename TVal, 
           class TPr, 
           class TAl
           template<typename,typename,class,class> TContainer >
void func(const TContainer<TKey, TVal, TPr, TAl>& container)
{
  for (typename TContainer<TKey, TVal, TPr, TAl>::iterator it = container.begin(); it != container.end(); ++it)
  {
    do_something(it->second);
  }
}
Run Code Online (Sandbox Code Playgroud)

但是,我想知道你为什么要这么烦.惯用的方法是传递迭代器:

template <typename FwdIt>
void func(FwdIt begin, FwdIt end)
{
  while(begin != end) {
    do_something(begin->second);
    ++begin;
  }
}
Run Code Online (Sandbox Code Playgroud)

这也允许您传递任何兼容的内容:

void f(const std::vector< std::pair<int, std::string> >& v)
{
   func( v.begin(), v.end() );
}
Run Code Online (Sandbox Code Playgroud)