Check at compile-time is a template type a vector

An alternative worth considering is to detect the presence of the push_back function using SFINAE. This is slightly more generic since it'll translate to other containers that implement push_back.

template<typename T>
struct has_push_back
{
    template<typename U>
    static std::true_type test(
        decltype((void(U::*)(const typename U::value_type&)) &U::push_back)*);

    template<typename>
    static std::false_type test(...);

    typedef decltype(test<T>(0)) type;
    static constexpr bool value = 
        std::is_same<type, std::true_type>::value;
};

Note that it currently only detects push_back(const T&) and not push_back(T&&). Detecting both is a little more complicated.

Here's how you make use of it to actually do the insert.

template<typename C, typename T>
void push_back_impl(C& cont, const T& value, std::true_type) {
    cont.push_back(value);
}

template<typename C, typename T>
void push_back_impl(C& cont, const T& value, std::false_type) {
    cont.insert(value);
}

template<typename C, typename T>
void push_back(C& cont, const T& value) { 
    push_back_impl(cont, value, has_push_back<C>::type());
}

std::vector<int> v;
push_back(v, 1);

std::set<int> s;
push_back(s, 1);

Honestly, this solution became a lot more complicated then I originally anticipated so I wouldn't use this unless you really need it. While it's not too hard to support const T& and T&&, it's even more arcane code that you have to maintain which is probably not worth it in most cases.


It is named tag dispatching :

#include <vector>
#include <set>
#include <type_traits>

template<typename T> struct is_vector : public std::false_type {};

template<typename T, typename A>
struct is_vector<std::vector<T, A>> : public std::true_type {};

template <typename T>
class X {
    T container;

    void foo( std::true_type ) {
        container.push_back(0);
    }
    void foo( std::false_type ) {
        container.insert(0);
    }
public:
    void foo() {
        foo( is_vector<T>{} );
    }
};

// somewhere else...
int main() {
    X<std::vector<int>> abc;
    abc.foo();

    X<std::set<int>> def;
    def.foo();
}

Tags:

C++

Templates