Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Writing a template that can use a std::vector or a std::set

Tags:

c++

templates

I've written an asynchronous job queue class which has been working nicely for ages. It uses a std::vector as the underlying collection to keep jobs in and then processes them later as you might expect. When I add a job it does a push_back on this vector.

Recently I decided that I wanted to templatize the underlying collection type that it uses and the with way I've written it, this should be very simple. It's now declared thus:

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

There's just one snag, for vectorish type containers I want to push things onto the end of the collection and call push_back, for settish type containers I'll want to call insert. How can I make a compile decision about which to call? Or is there a handy adapter I can use?

like image 445
Benj Avatar asked Mar 22 '13 15:03

Benj


1 Answers

I would rather use an overloaded helper function. The one below relies on the fact that no Standard container exposes both a single-argument insert() function and a push_back() function:

#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));
}

This is how you would use them:

#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();
}

And here is a live example.

like image 76
Andy Prowl Avatar answered Oct 04 '22 02:10

Andy Prowl