c++classtemplatesshift

How to implement a template class in c++?


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.


Solution

  • 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.