编写一个可以使用std :: vector或std :: set的模板

时间:2013-03-22 15:48:05

标签: c++ templates

我编写了一个异步作业队列类,它已经很好地工作了很长时间。它使用std::vector作为底层集合来保留作业,然后按照您的预期稍后处理它们。当我添加作业时,它会在push_back上执行vector

最近我决定要模仿它使用的底层集合类型以及我编写它的方式,这应该非常简单。现在宣布:

template<typename J, typename CollectionT = std::vector<J>>
class async_jobqueue
{
public:

只有一个障碍,对于矢量型容器,我想把东西推到集合的末尾并调用push_back,对于我想要调用insert的定居类型容器。如何做出关于调用哪个的编译决定?或者我可以使用一个方便的适配器吗?

3 个答案:

答案 0 :(得分:5)

我宁愿使用重载的辅助函数。下面的内容依赖于以下事实:没有标准容器暴露单参数insert()函数和push_back()函数:

#include <utility>

template<typename C, typename T>
auto insert_in_container(C& c, T&& t) ->
    decltype(c.push_back(std::forward<T>(t)), void())
{
    c.push_back(std::forward<T>(t));
}

template<typename C, typename T>
auto insert_in_container(C& c, T&& t) ->
    decltype(c.insert(std::forward<T>(t)), void())
{
    c.insert(std::forward<T>(t));
}

这就是你如何使用它们:

#include <set>
#include <vector>
#include <iostream>

int main()
{
    std::set<int> s;
    std::vector<int> v;

    insert_in_container(s, 5);
    insert_in_container(v, 5);

    std::cout << s.size() << " " << v.size();
}

这是一个live example

答案 1 :(得分:3)

insert(iterator, value_type)重载怎么样,并用end()调用它?它可用于两者,应该做你想要的!也适用于std::list

这里真的不需要进行类型调度。

答案 2 :(得分:2)

由于concepts-lite有希望及时出现在C ++ 14中,我不妨告诉你如何做到这一点:

template<typename J, typename CollectionT = std::vector<J>>
class async_jobqueue
{
  public:

    requires Associative_container<CollectionT>()
    void adding_function(const J& item) {
      // Uses insert
    }

    requires Sequence_container<CollectionT>()
    void adding_function(const J& item) {
      // Uses push_back
    }
};

当然,这还不可能(也可能永远不会)。然而,接受Concepts-lite是非常积极的。