Skip to content

Latest commit

 

History

History
87 lines (71 loc) · 3.38 KB

File metadata and controls

87 lines (71 loc) · 3.38 KB

Lab 13 — A Templated DataStore<DataSet>: Insertion Idioms and Cached Sorting

Goal

Practice a few template techniques beyond everyday generic-function usage: overload resolution between value/rvalue insertion paths, perfect forwarding, and taking a callable as a template parameter instead of std::function.

Description

DataStore holds a collection of DataSet (a name plus a vector<double>) in a std::vector, chosen specifically so it can be sorted in place — an associative container such as std::map would need a random-access iterator it doesn't provide, and would have to be rebuilt with a custom comparator to change ordering. Iteration is exposed directly through the underlying vector's iterator (begin()/end()), since a dedicated iterator type isn't needed here.

Two insertion paths

  • addDataset(std::string name, std::vector<double> nums) — the copy-and-move path: name and nums are taken by value (so the caller's arguments are copied, or moved if the caller passes rvalues), then both are moved into the stored DataSet.
  • template <typename T> addDataset(T&& dataset) — the perfect-forwarding path: a single template handles an existing DataSet passed as an lvalue, a const lvalue, or an rvalue/prvalue, forwarding it through to push_back so the right one of copy/move is chosen automatically for each case.

Sorting without std::function

sort(func, order) takes the comparison metric as a template parameter (T func) rather than as a std::function, so the call is resolved at compile time and avoids the virtual-call/vtable indirection that std::function's type erasure would otherwise add on every comparison. func is invoked with a DataSet's _nums begin/end iterators and returns a double metric to sort by. Because that metric can be expensive to compute, sort evaluates it once per element up front into a cache vector and reuses those cached values for every comparison during the sort, instead of recomputing the metric each time two elements are compared.

main demonstrates both insertion paths and sorts by average value (via std::accumulate/std::distance over each dataset's numbers), printing the collection before and after sorting.

Project structure

include/DataStore.h    SortingDirection, DataSet, DataStore<DataSet>
src/main.cpp            exercises both insertion paths and sort()

Requirements

  1. Compiles cleanly with -Wall -Wextra -pedantic.
  2. DataStore stores DataSet in a std::vector and exposes begin()/ end() for iteration.
  3. Two addDataset overloads exist: one following the copy-and-move idiom for an explicit name/values pair, and one perfect-forwarding template for an existing DataSet.
  4. sort() takes the comparison metric as a template parameter (not std::function) and computes/caches it once per element rather than recomputing it on every comparison.

Expected output

Before sorting:
Tank 1: [12.5, 15.2, 14.8, 13.1]
Tank 2: [22, 19.5, 21.3, 20.7]
Tank 3: [8.4, 7.9, 9.1, 8.7]
Tank 4: [31.2, 29.8, 30.5, 32.1]
Tank 5: [17.6, 18.2, 16.9, 17.3]
Tank 6: [12.6, 2.2, 21.3, 11.5]
Tank 7: [51.2, 32.1, 16.5, 22.4]

After sorting:
Tank 3: [8.4, 7.9, 9.1, 8.7]
Tank 6: [12.6, 2.2, 21.3, 11.5]
Tank 1: [12.5, 15.2, 14.8, 13.1]
Tank 5: [17.6, 18.2, 16.9, 17.3]
Tank 2: [22, 19.5, 21.3, 20.7]
Tank 7: [51.2, 32.1, 16.5, 22.4]
Tank 4: [31.2, 29.8, 30.5, 32.1]