我正在实现完全相同的四种算法,除了他们使用的数据结构 - 两次使用priority_queue
,一次使用stack
,最后一次使用{{ 1}}。它们相对较长,所以我想只有一个函数模板接受容器类型作为模板参数,然后让每个算法用适当的参数调用该模板,如下所示:
queue
我已经设法通过基于template <class Container>
void foo(/* args */)
{
Container dataStructure;
// Algorithm goes here
}
void queueBased(/* args */)
{
foo<queue<Item> >(/* args */);
}
void stackBased(/* args */)
{
foo<stack<Item> >(/* args */);
}
和priority_queue
的实现做到了这一点,但我不能对基于stack
的算法做同样的事情,因为它使用了访问最重要元素的不同名称(queue
而不是front( )
)。我知道我可以专门针对这种情况使用模板,但后来我会有大量的重复代码(我正在努力避免这种情况)。
实现这一目标的最佳方法是什么?我的第一个本能是为队列创建一个包装类,它添加了一个等同于top( )
的{{1}}操作,但我一直在读这个子类化STL类是禁止的。那我该怎么办呢?
答案 0 :(得分:7)
您可以在容器适配器的类型上写一个非成员top
函数:
template <typename T>
T& top(std::stack<T>& s) { return s.top(); }
template <typename T>
T& top(std::queue<T>& q) { return q.front(); }
// etc.
如果您实际使用带容器适配器的不同序列容器(通过其Sequence
模板参数),则需要适当修改重载以处理它。
直接使用序列容器(例如std::vector
)而不是使用其中一个序列适配器可能更直接。
答案 1 :(得分:2)
您可以使用部分特化来选择正确的方法:
template<class Container>
struct foo_detail {
static typename Container::value_type& top(Container &c) { return c.top(); }
static typename Container::value_type const& top(Container const &c) { return c.top(); }
};
template<class T, class Underlying>
struct foo_detail<std::queue<T, Underlying> > {
typedef std::queue<T, Underlying> Container;
static typename Container::value_type& top(Container &c) { return c.front(); }
static typename Container::value_type const& top(Container const &c) { return c.front(); }
};
template<class Container>
void foo(/* args */)
{
Container dataStructure;
// Use foo_detail<Container>::top(dataStructure) instead of dataStructure.top().
// Yes, I know it's ugly. :(
}
答案 2 :(得分:1)
您可以在不使用继承的情况下围绕std::queue
创建包装器;事实上,继承将是错误的工具,因为你试图装饰一个queue
而不是精炼或扩展 queue
。这是一种可能的实现方式:
template <typename QueueType>
class QueueWrapper {
public:
explicit QueueWrapper(const QueueType& q) : queue(q) {
// Handled in initializer list
}
typedef typename QueueType::value_type value_type;
value_type& top() {
return queue.front();
}
const value_type& top() const {
return queue.front();
}
void pop() {
queue.pop();
}
private:
QueueType queue;
};
希望这有帮助!
答案 3 :(得分:0)
queue
,priority_queue
和stack
都是容器适配器;它们是底层容器的包装器(默认情况下,deque
为queue
,stack
为vector
,priority_queue
为vector
。
由于deque
,list
和{{1}}(“真正的”容器类)共享大多数方法,因此您可以删除中间人并使用这些类。
请记住, public 继承对于STL容器来说不是一个好主意; 私有继承是可以的(也可能是你想要的)。
答案 4 :(得分:-1)
front()
和top()
特定于某些类型的容器,但所有STL容器都支持*begin()
。