Template Specialization for T & # 8594; std :: vector <T>

I have a template class method

template<class T>
T pop<T>();

Now I want to make the template specialization as follows:

template<class T>
std::vector<T> pop<T>();

I can not do anything,

template<>
std::vector<int> classname::pop<std::vector<int>>();

But I still need to leave this type as a template parameter. How to do it?


EDIT: Thanks to Piotr, I ended up using tag sending. Below is the code of what I was doing,

// The public method that is accessed by class.push<std::vector<int>>(12);
template<class T>
void push(T data) {
    push(tag<T>(), data);
}

// The private method that calls the actual vector push for vector types
template<class T>
void push(tag<std::vector<T>>, std::vector<T> const& data_vector) {
    push_vector(data_vector);
}

// The actual implementation
template<class T>
void push_vector(std::vector<T> const& data_vector) {
// Actual implementation in here
}
+4
source share
3 answers

On top of my head, I usually get around using a one-term structure:

template <typename T>
struct pop_impl {
    static T pop(classname& x); // normal function
};

template <typename T>
struct pop_impl<std::vector<T>> {
    static std::vector<T> pop(classname& x); // specialized for std::vector<T>
};

template <typename T>
T classname::pop() { return pop_impl<T>::pop(*this); }
+5
source

A possible solution is a non-member function implemented like this

template <class T>
struct classname_pop
{
    static T pop(classname &obj) { return obj.pop() ;}
}

template <class T>
struct classname_pop<std::vector<T>>
{
   static std::vector<T> pop(classname &obj) {obj.specialized_pop() ;}
}

template <class T>
T classname_pop(classname &obj)
{
   return classname_pop_t<T>::pop() ;
}
+1
source

:

:

#include <algorithm>
#include <iostream>
#include <vector>

class Stack
{
    private:
    std::vector<int> m_data;

    class Pop {
        friend class Stack;

        public:
        Stack& stack;

        Pop(Stack& stack)
        :   stack(stack)
        {}

        private:
        Pop(const Pop&) = default;
        Pop& operator = (const Pop&) = default;

        public:
        operator int () {
            std::vector<int>& data = stack.m_data;
            int result = -1;
            if( ! data.empty()) {
                result = data.front();
                data.erase(data.begin());
            }
            return result;
        }

        operator std::vector<int> () {
            std::vector<int>& data = stack.m_data;
            std::size_t size = std::min(data.size(), std::size_t(3));
            std::vector<int> result(data.begin(), data.begin() + size);
            data.erase(data.begin(), data.begin() + size);
            return result;
        }
    };

    public:
    Stack()
    :   m_data( {0, 1, 2, 3, 4, 5, 6, 7, 8} )
    {}

    const std::vector<int>& data() const { return m_data; }
    Pop pop() { return Pop(*this); }
};

int main()
{
    Stack stack;
    int i = stack.pop();
    std::vector<int> v = stack.pop();
    std::cout << "i = " << i << '\n';
    std::cout << "v = {";
    for(auto i : v)
        std::cout << i;
    std::cout << "}\n";
}

Disclaimer . I believe that the code is completely useless (it may turn out to be useful if there is pop () just returning the same value and pop (std :: size_t) converting to different containers where the Pop destructor does the erasure).

0
source

All Articles