Changelog:

  • 19 Apr 2023: correct reference to CSO1 C++ lab; remove requirement for mixed-item initializer list not to compile

We showed you some basic C++ last semester, including using templates like Java uses generics. But that is far from all C++ templates can do… This lab will help you explore this topic in more detail.

We recommend that you work in pairs for this lab, like those before it.

1 Caveat

There exists a subset of programmers who believe that C++ templates beyond type generics are an abomination and should never be used. I hope this lab will help you make your own opinion, but be aware that if you work for a company that uses C++ and suggest some of these techniques, you might get some blow-back…

2 Review

Begin by reviewing the C++ lab from CSO1.

We’ll be picking up from where those left off in this lab.

3 A Mathematical Vector type

In mathematics, a vector has fixed length and adding vectors of different length is meaningless. In this lab you’ll use C++ templates to make a mathematical vector class that uses the type checker to ensure at compile time that no wrong-sized operations occur.

Implement a templated mathematical vector type in C++. When you are done, the following code should do as the comments suggest (you’ll need to comment out the does not compile lines to get the others to work):

typedef vec<double, 2> vd2;
typedef vec<double, 3> vd3;
typedef vec<int,4> vi4;

int main() {
    vd3 a;
    std::cout << a << std::endl; // prints (0, 0, 0)
    
    a[2] = 2.5;
    std::cout << a << std::endl; // prints (0, 0, 2.5)

    std::cout << (a + a) << std::endl; // prints (0, 0, 5)
    std::cout << a << std::endl; // prints (0, 0, 2.5)

    vd2 b;
    std::cout << b << std::endl; // prints (0, 0)
    vi4 c;
    std::cout << c << std::endl; // prints (0, 0, 0, 0)
    
    std::cout << (a + b) << std::endl; // does not compile
    std::cout << (a + c) << std::endl; // does not compile
    
    
    c[2] = 2.5; // implicitly casts a double to an int...
    b[1] = 2.5;
    c[2] = 2;

    std::cout << b << std::endl; // prints (0, 2.5)
    std::cout << c << std::endl; // prints (0, 0, 2, 0)
    vd3 x = {1.5, 2.5, 3.5};
    std::cout << x << std::endl; // prints (1.5, 2.5, 3.5)

    vd3 y = {1, 2, 3};
    std::cout << y << std::endl; // prints (1, 2, 3)
}

You code should not contain any heap-allocated memory (no new or malloc)

When you’re done submit your C++ files to the submission site, OR show your TA what you’ve done for check-off.

4 Guides

5 C++ Iterators

Many STL structures in C++ use the iterator pattern to allow access. This has a somewhat different look than it does in Java or the like.

The collection offers two functions of note:

The iterator overloads three operators of note:

Thus, a loop that prints all items in a collection might look like

for(auto it = mycollection.begin(); // create an iterator
    it != mycollection.end();       // and while it's not off the end
    ++it) {                         // move it forward
    std::cout << *it << std::endl;  // derreference to print
}

Note in the above that when you combine a declaration and initialization, you can declare the type to be auto meaning use whatever type the initialization gives me.