Software Design (C++) - Exercises VI  (1 - 4),   11 - 12 Dec , 2014   


  1. Reimplement the class Complex (from the Exercise 3.3) as a class template:
      template <typename T>
      class Complex { 
        ...
      };
    
    T is the concrete number type used by the template. Analyse the requirements (operations or any characteristics) imposed by the template on the concrete type T. Can we help the user to check at compilation time if the template parameter (=type) she has defined satisfies the requirements (hint: static_assert, type traits)? Illustrate how to instantiate the template and use the generated classes.

  2. Sketch out an implementation of a singly-linked list as a C++ class SList. Assume that the list element type is std::string. Provide the essential parts of a class definition and implementations for the default constructor and the destructor. Provide implementations for the push_front (insert an element to the beginning) and pop_front (remove the first element ) operations. Note that the first element is accessed by a separate operation, front(), that returns a reference to that element, if any.

  3. Sketch out an implementation of an iterator for the singly-linked list discussed in the previous exercise. Follow the STL conventions and overload your iterator abstraction to look like a C-style pointer (providing: "++", "->, "*", etc.). For a general description of the iterator abstraction, see the Wikipedia item: Iterator and the section discussing C++ iterators, or see the cppreference.

    Provide a class definition for the list iterator and implementations for its prefix and postfix ++ operations. Implement the postfix ++ operation in terms of the prefix ++. Show how to provide the appropriate iterator typedef or using inside your singly-linked list. Implement the begin() and end() operations that return iterators to the first element and "beyond" the last element, respectively. Note that the end iterator only acts as a kind of placeholder; attempting to access via it results in undefined behavior. You need to consider only the non-const iterators.

  4. Here is a snippet of code (shown during lectures) from the simple Vector implementation. The code shows the definition of the (non-const) iterator for Vector. Why is this kind of straightforward implementation (that exposes the underlying storage) of an iterator risky? Show what disastrous actions a malicious (or just careless) user could take given this iterator.
    class Vector {
    public:
    	...
    	//iterator
    	using iterator = double*; // can change the contents in-place
    
    	iterator begin() { return elem; }		
    
    	iterator end() { 
    		if (elem) return elem + sz;
    		return nullptr;
    		//return elem + sz;  // (would work also because nullptr + 0 == nullptr)
    	}
    	...
    
    private:
    	int sz;
    	double * elem;
    	int space;
    };