How to implement a template class in c++?

174 Views Asked by At

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.

2

There are 2 best solutions below

2
Ted Lyngmo On BEST ANSWER

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.

0
Zelei Ádám István On

I got it right finally, too bad it's too late now. Thanks everybody for the help!

#ifndef SHIFTER_H
#define SHIFTER_H
template <class T, class U>
class shifter {
  T* container;
  U type;
public:
  shifter(T& c): container(&c) {}
  void shift(int n) {
    if(n < 0){
      n = -n;
      for(int i = 0; i < n; i++){
        type = container->front();
        for(int j = 1; j < container->size(); j++){
          container->at(j-1) = container->at(j);
        }
        container->back() = type;
      }
    } else if(n > 0){
      for(int i = 0; i < n; i++){
        type = container->back();
        for(int j = container->size() - 2; j >= 0; j--){
          container->at(j+1) = container->at(j);
        }
        container->at(0) = type;
      }
    }
  }
};
#endif