All arguments use their declared C++ parameter types. Strings are case-sensitive. Ingredients and steps are lists of strings; empty lists, empty items, and duplicates are allowed and preserve order. Every returned value record/list is a detached snapshot, including nested lists. Instances must have independent state. No persistence or deletion is required.
Prototype: implement RecipeDraft(name, ingredients, steps) and snapshot(). The snapshot is the fields declared in the value record below. Copy the input lists. The draft does not validate the name or manage permissions.
Final: implement RecipeManager() with these methods:
add_user(): permissions is a list containing only"read"and/or"write"; duplicates are harmless. Empty permissions are allowed. Empty user IDs or unknown permissions raisestd::invalid_argument, even for an existing ID. Returnfalsefor an existing valid ID, preserving its original permissions; otherwise register a copied permission set and returntrue.add(): requires write. Empty name raisesstd::invalid_argumentbefore permission checks. Returnnulloptfor no permission or a currently used name. Success returns"recipe1","recipe2", ... and creates v1. Rejected requests consume no identifier.update(): the same name validation and write check apply. Missing recipe or name owned by another recipe returnsnullopt. Success appends a revision, even for identical content, and returns its number. Renaming frees the old current name.get(): requires read.nulloptselects latest; an integer version selects that positive revision. Returnnulloptfor no permission, missing recipe, or nonexistent version. A snapshot has exactlyid,version,name,ingredients, andsteps.history(): requires read. Return snapshots in increasing version order, or[]for no permission/missing recipe.rollback(): requires write; invalid target, missing recipe, or conflicting historical name returnsnullopt. Append the selected content as a new latest revision and return its number. Preserve all existing versions and the same recipe ID.by_ingredient(): requires read; otherwise[]. Match exact ingredient membership in current content. Sort by ingredient count ascending, current name ascending, then ID ascending. A recipe appears once despite duplicate ingredients.
Invalid or rejected calls leave all state unchanged.
The public C++ API below is authoritative for field types and return values. erase is used where another language might use a method named delete, because delete is a C++ keyword. Returned records are value snapshots with the documented named fields; mutating a record or its nested vectors cannot affect the service.
struct DraftSnapshot {std::string name;Strings ingredients,steps;bool operator==(const DraftSnapshot&)const=default;};
struct Recipe {std::string id;Int version;std::string name;Strings ingredients,steps;bool operator==(const Recipe&)const=default;};
class RecipeDraft { public:
RecipeDraft(std::string name,Strings ingredients,Strings steps);
DraftSnapshot snapshot() const;
};
class RecipeManager { public:
RecipeManager();
bool add_user(const std::string& id,const Strings& permissions);
Opt<std::string> add(const std::string& user,const std::string& name,const Strings& ingredients,const Strings& steps);
Opt<Int> update(const std::string& user,const std::string& id,const std::string& name,const Strings& ingredients,const Strings& steps);
Opt<Recipe> get(const std::string& user,const std::string& id,Opt<Int> version=std::nullopt) const;
Vec<Recipe> history(const std::string& user,const std::string& id) const;
Opt<Int> rollback(const std::string& user,const std::string& id,Int version);
Strings by_ingredient(const std::string& user,const std::string& ingredient) const;
};Compile and run from this directory:
c++ -std=c++20 -O2 -Wall -Wextra -pedantic -pthread main.cpp -o practice
./practice --stage prototype
./practice --stage finalEdit exercise.hpp. Both stages start unfinished and must report failures until implemented. Keep main.cpp as the executable contract. The runner returns nonzero for a failed check, an unexpected exception, an invalid stage, or an empty suite. C++20 and only the standard library are required.
Complete the starter code, then run the checks.
Results and errors will appear here.
C++ runtime powered by Wasmer.