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
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
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
:
:
#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