For this assignment, you will implement a templated STL-like container
called a Shift-Over List, or Sol.
You will turn in a single file, Sol.h.
You may use C++11 features.
An Sol takes three template parameters:
find is called (default is 1).
Behavior is undefined if this value is negative.
Whenever you search for an element using find, it’s moved this much
closer to the start of the list. The most popular items
migrate to the front of the list for quick access.
std::less).
Here are several example programs:
#include "Sol.h"
#include <iostream>
using namespace std;
int main() {
Sol<int> foo;
foo.insert(2);
foo.insert(5);
foo.insert(3);
// Should print "253"
for (Sol<int>::iterator it = foo.begin(); it != foo.end(); ++it)
cout << *it;
cout << '\n';
return 0;
}
#include "Sol.h"
#include <iostream>
#include <cassert>
#include <cstring>
#include <sstream>
using namespace std;
template<typename T>
string cat(const T &con) {
ostringstream os;
for (typename T::iterator it = con.begin(); it != con.end(); ++it)
os << *it;
return os.str();
}
int main() {
char data[] = "abcdefghXYZ";
Sol<char,4> foo(data, data+strlen(data));
Sol<char,4>::iterator it;
foo.erase('X');
cout << cat(foo) << '\n'; // Should print abcdefghYZ
it = foo.find('Z');
assert(it != foo.end());
assert(*it == 'Z');
cout << cat(foo) << '\n'; // Should print abcdeZfghY
foo.find('Z');
cout << cat(foo) << '\n'; // Should print aZbcdefghY
foo.find('Z');
cout << cat(foo) << '\n'; // Should print ZabcdefghY
return 0;
}
#include "Sol.h"
#include <iostream>
#include <cassert>
#include <cstring>
#include <sstream>
using namespace std;
template<typename T>
string cat(const T &con) {
ostringstream os;
for (typename T::iterator it = con.begin(); it != con.end(); ++it)
os << *it;
return os.str();
}
int main() {
Sol<int> foo;
for (int i=1; i<=9; i++)
foo.insert(i);
cout << cat(foo) << '\n'; // Should print 123456789
cout << cat(foo+3) << '\n'; // Should print 789123456
cout << cat(foo) << '\n'; // Should print 123456789
++foo;
cout << cat(foo) << '\n'; // Should print 912345678
foo -= 2;
cout << cat(foo) << '\n'; // Should print 234567891
return 0;
}
#include "Sol.h"
#include <cassert>
#include <iostream>
#include <sstream>
using namespace std;
// A simple wrapper around a float.
class Age {
public:
Age() : years(0.0) { }
Age(float y) : years(y) { }
float years;
};
// Note that you CAN'T compare two Age objects using < or ==.
// This compares two Age objects, but only the integral portion.
// Therefore, it is NOT the case that 5.3 compares less than 5.4;
// they’re both the same as far as we’re concerned.
class AgeCompare {
public:
bool operator()(Age a, Age b) const {
return int(a.years) < int(b.years);
}
};
int main() {
Sol<Age, 0, AgeCompare> who;
who.insert(1.25); // a baby
who.insert(54.45); // Jack
who.insert(20); // a typical student
assert(who.find(1.00) != who.end()); // should succeed
assert(who.find(1.25) != who.end()); // should succeed
assert(who.find(1.99) != who.end()); // should succeed
assert(who.find(2.00) == who.end()); // should fail
assert(who.find(53.45) == who.end()); // should fail
assert(who.find(54.00) != who.end()); // should succeed
assert(who.find(54.45) != who.end()); // should succeed
assert(who.find(54.78) != who.end()); // should succeed
assert(who.find(55.78) == who.end()); // should fail
assert(who.find(19.99) == who.end()); // should fail
assert(who.find(20.00) != who.end()); // should succeed
assert(who.find(20.11) != who.end()); // should succeed
assert(who.find(20.99) != who.end()); // should succeed
assert(who.find(21.00) == who.end()); // should fail
assert(who.find(21.01) == who.end()); // should fail
assert(who.count(54.1) == 1); // Are we using the functor?
cout << "Success! Promotions for everyone!\n";
}
The type stored by this templated class has the following requirements:
==, <, etc., be valid for the
stored types. Your code must not use such operators—it must use
the comparison functor, which should default to the less<T> functor.
SolThe following types are required, and have similar meanings as they do in the standard STL containers:
size_type (must be an unsigned integral type)
key_type
value_type
iterator
SolSol.
iterator begin() const
iterator end() const
bool empty() const
size_type size() const
size_type max_size() const
iterator find(const key_type &)
end() if not found.
size_type count(const key_type &) const
iterator insert(const key_type &)
iterator insert(iterator, const key_type &)
size_type erase(const key_type &)
void erase(iterator)
void erase(iterator, iterator)
void clear()
Sol + N or N + Sol (where N is an int)
Sol, rotated right by N places.
size().
Sol - N or N - Sol (where N is an int)
Sol, rotated left by N places.
size().
Sol += N
Sol = Sol + N;
Sol -= N
Sol = Sol - N;
Sol::iterator:==
!=
->
g++ -std=c++0x
#include guards.
using declarations.
list, no vector, no set, no string, etc.
pair, etc.
system, popen,
fork, exec, etc.
Sol
active at the same time, and they must not interfere with each other.
insert and erase operations to invalidate
all existing iterators. It is also acceptable for insert and erase
to not invalidate any iterators. It’s up to you.
find may invalidate iterators pointing to any
element moved, but no others.
Sol may be changed after it has been
placed into the collection. *iter = whatever; must compile.
const-correctness. We may try to assign
a const Sol to a non-const Sol, take the size() of
a const Sol, etc.
operator<< or a .print() method, so you can see what’s
going on in your container.
erase methods via copy-and-paste.
// TODO comments to
mark where you need to go back and use it.
Follow the directions on the homework page.
Turn in someone else’s work.