\title{A5: Generic Programming} \input{preamble.tex} In this exercise a matrix class is being developed and gradually evolved into a typesafe templated component. \bigskip I decided to use one of the standard containers for storing the elements of the matrix and initially went with \texttt{std::vector}. But since we were going to do arithmentics on the data, and no requirements were made as to the arithmentics actually being those of a real matrix, I figure why not use \texttt{std::valarray} and have all arithmentic operations be per-entry, re-using the behaviour of \texttt{std::valarray} directly. During this change I discovered that \texttt{std::valarray} and \texttt{std::vector} ctor args for creating with a size and a default value for all items are reversed, which would not be caught by the compiler with both of them being integral: \footnotesize\begin{lstlisting}[language=C++] explicit vector( size_type count, const T& value = T(), const Allocator& alloc = Allocator() ); valarray( const T& val, std::size_t count ); \end{lstlisting}\normalsize That, I think, is rather unfortunate. When using a standard container, all memory managing is handled by the container, even when throwing an exception inside the constructor, so tere is no need to do anything clever inside the matrix implementation itself. Otherwise a allocating base-class could have been made for memory ownership as seen during one of the presentations. The implementation for the statically typed \texttt{Imatrix} can be seen in the \texttt{imatrix.h} file. I first wrote the entire \texttt{Imatrix} class with the values dynamically allocated inside the \texttt{std::valarray} but wanted to explore having the matrix dimenions available at compile-time (matrices doesn't have the habit of changing their sizes dynamically, so they should be checkable at compile-time). I did this with template size arguments. First of all, this removed a lot of error checks on matrix dimension matching, which is now part of the type itself. It also removed the need for the two integer members from the first imeplementation, carrying the matrix dimensions, so the change now also saved 16 bytes of memory. And, best of all, we get a compile error if for example we try multiplying two matrices where their dimensions doesn't adhere to the algebraic rules! For the \texttt{Row()} and \texttt{Column()} I briefly considered returning a span to be able to return references to a row or column for dynamic iteration, but decided to stick with the \texttt{std::vector} as described in the assignment. The code for the size-templated \texttt{Imatrix} can be seen in the \texttt{imatrix\_nm.h} file. \bigskip Next step was to templatize the underlying type of the matrix. This was more or less done by simply replacing \texttt{int} with \texttt{T} and all the places where 0 is assigned to the value type, replacing it with the default value \texttt{T\{\}}. For the \texttt{Move()} function a $0$ assignment was needed and this I replaced with an empty initializer list, \texttt{\{\}}. The new templatized class is called \texttt{Matrix} and can be found in the \texttt{matrix.h} file. When instantiating a template only the required/used functions are generated (or so it appears). In other words; a \texttt{Matrix c1} can be instantiated without getting any compile errors as long as no algebraic methods are being called on it. If the line \texttt{c1 + 1} is added somewhere it will complain about not being able to add with \texttt{int}, but not any of the other unused operations. When adding the requirements of concepts, I expect to get errors for all the uses, not just the ones used in the program. In other words, concepts might end up requirering more work to be done by a developer than strictly needed. This might not always be desirebale - or at least it is something that should be thought about when designing a new component. One option to mimic the same behaviour, but with concepts, could perhaps be to add requirements to each of the member functions. This is however not what I did in this exercise. I made a concept, \texttt{supports\_modulo}, used for only ``activating'' the modulo operator if the underlying type supports it. I made an extensive, templated, test function that exercised all operator types of any of the matrix types - and here the compiler errors for \texttt{Chess\_piece} were not very helpful (the same goes for \texttt{std::string}). This can be seen in the \texttt{matrix.cc} file. In the test program, to prevent performing modulo operations on matrices that doesn't support them, I used the \texttt{supports\_modulo} concept together with a \texttt{if constexpr} to only try to call the module operator when enabled for the class. I made another concept, \texttt{supports\_matrix}, used for the underlying type of the \texttt{Matrix} class itself, requirering algebraic functionality on the underlying type. After adding requirements for all the needed operators, the \texttt{Chess\_piece} and \texttt{std::string} matrices now failed as expected but this time with a much shorter and to-the-point error message telling me exactly what would be needed for them work. I added empty dummy operator functions to fulfill the requirements (and commented out the \texttt{std::string} one) and now the program compiles and runs as expected. In hindsight, using the \texttt{std::valarray} may have resulted in me writing less code in the \texttt{Matrix} implementation, but because of implementation details inside \texttt{std::valarray} I may have ended up having to write more algebraic operators on \texttt{Chess\_piece} to get it to work. \bigskip The approach of first writing the statically typed class, then templatizing it, and finally analyzing the actual requirements of the underlying type and expressing those as a concept requirements, was a nice way to ``eat the elephant'', being able to focus on just one aspect of the code at one time. My guess is also that it would have been hard to foresee what the actual type requirements would end up being without having written the code yet. \end{document}