2011-09-30 72 views
2

我想知道如何编写一个函数,可以接受作为参数的一个关联容器,它本身接受两个或多个模板参数。例如,如果我想编写一个适用于std :: map的函数,则可以编写如下所示的内容。关联容器作为函数模板参数

template <class Map, class Key, class Value, class Compare, class Allocator> 
void foo(Map<Key, Value, Compare, Allocator>& map); 

但是,这对boost :: unordered_map不起作用,因为boost :: unordered_map接受5个模板参数。我可以将地图作为单个模板参数接受,并使用它应该支持的特征以便稍后推导出键和值类型,但对于嵌套地图,代码变得非常冗长且难以维护。有没有更简单的方法来编写这样的函数,但仍然可以用于任何接受大于或等于2的模板参数的任何关联容器?

请注意,接受迭代器而不是容器作为参数是不够的,因为我需要更多关于迭代器在其上运行的容器的信息,而不是迭代器可以提供的信息。

非常感谢!

回答

2

为什么不直接使用简单的方法用一个模板参数:

template <typename C> void foo(const C & container) 
{ 
    typedef typename C::key_type key_type; 
    typedef typename C::mapped_type mapped_type; 

    // etc. 
} 

你可以添加一些成员类型检查typetraits是你想要的那些成员类型存在额外的检查,但可能不会放弃任何额外的好处。

或者,你可以做一些通用的模式匹配,虽然只带班,而不是功能:

template <typename> struct AtLeastTwo; 

template <typename K, typename V, typename ...Args> 
struct AtLeastTo<K, V, Args...> 
{ 
    // now have types K and V 
}; 

typedef std::unordered_map<int, Foo, MyHash> map_type; 
AtLeastTwo<map_type> m; 
// ... 
+0

对于嵌套地图,代码变得非常冗长,特别是如果内部地图的外部地图类型不同。提取所有正确的类型需要使用Boost.TypeTraits进行大量的类型操作。我只是想知道是否有一种更简单的方法来做到这一点,而不使用特质来反思价值观,但我想不是。 –

+0

嵌套地图添加的复杂性究竟是什么?我不确定你想要达到什么目的;通过观察它,任何涉及的类型本身是否是地图都无关紧要。 –

+0

是的,但如果我需要迭代器来处理外部映射和内部映射中的类型,无论它们的const限定或它们是否为指针或引用,都需要使用多个重载方法创建实用程序类,以完成一些简单的任务。 –

0

A型不传达它是否是一个关联序列信息,这是一个语义意义。如果你不想支持各种关联序列,按照标准接口,最好的选择是使用单个模板参数,并使用特征来反思其键/值类型等等。

+0

这就是我现在正在做的,但是支持使用特征的嵌套地图的样板代码本身就是几百行,所以我想知道是否有更简单的方法来解决这个问题。然而,在阅读了两个答案之后,我认为没有更简单的方法。 –