I'm learning c++ at uni for a few months so I'm a beginner and in my exam I encountered a problem with template class. The task was to implement a template class in a header file like it was given in the main method.
#include <iostream>
#include "shifter.h"
#include <string>
#include <deque>
#include <vector>
struct string_size_less
{
bool operator()( const std::string& lhs,
const std::string& rhs ) const
{
return lhs.size() < rhs.size();
}
};
const int max = 1024;
int main()
{
std::vector<int> vm;
for( int i = 0; i < max; ++i )
{
vm.push_back( i );
}
std::string s = "Hello World!";
std::deque<double> d;
d.push_back( 3.45 );
d.push_back( 7.89 );
d.push_back( 2.12 );
shifter<std::string, char> ssh( s );
shifter<std::deque<double>, double> dsh( d );
shifter<std::vector<int>, int> vsh( vm );
vsh.shift( -3 );
vsh.shift( 1 );
ssh.shift( 27 );
ssh.shift( 3 );
dsh.shift( -10 );
}
The task was to implement the shifter template class in the shifter.h file. The catch was that it can take all kinds of array-like containers, like string, vector, deque, etc. And then the shift method move the items in the list by a given number, if its positive, then move to the right by 3 for example, if its negative move left the same way. I was clueless how to write my shifter class to work like that. Any suggestions on how to start, how should the header file look like?
I tried writing the class, like we used to in class.
template<class T, class U>
class shifter {
T cont;
U type
public
shifter(T arr) {}
But honestly i absolutely got no clue how to do this.
Any suggestions on how to start, how should the header file look like?
Start by making it capable of storing a reference or pointer to the container it should operate on. You probably only need one template parameter in your case. Here's an example where it stores a pointer to the container.
template <class C>
class shifter {
public:
shifter(C& c) : m_container(&c) {}
private:
C* m_container;
};
Then you need to implement the void shift(...)
member function. For shifting left or right you could use the standard algorithm std::rotate
to which you supply three iterators: The beginning of the range, the new first element and the "one passed last" iterators.
One possible implementation of the shift
member function:
#include <algorithm> // std::rotate
#include <iterator> // std::next / std::prev
// ...
void shift(typename C::difference_type x) {
if(x < 0) {
x = -x;
x %= std::size(*m_container);
// call std::rotate here with the proper iterators:
// std::begin(*m_container)
// std::next(std::begin(*m_container), x) // the new first element
// std::end(*m_container)
} else if(x > 0){
x %= std::size(*m_container);
// call std::rotate here with the proper iterators:
// std::begin(*m_container),
// std::prev(std::end(*m_container), x) // the new first element
// std::end(*m_container)
}
}
It will however not work on all containers in the standard library, but it'll work on most where it makes sense.