Exercise: Search, “User Not Found” Exception¶
What’s Wrong?¶
In
Exercise: Search a User By Lastname
we chose to implement the UserDB::search_by_lastname()
method to
return an instance of User
,
class UserDB
{
public:
...
User search_by_lastname(const std::string& lastname) const;
...
};
This leads to unnatural coding in the not-found case: an empty/invalid user has to be returned:
User UserDB::search_by_lastname(const std::string& lastname) const
{
for (size_t i=0; i<_users.size(); i++)
if (_users[i].lastname() == lastname)
return _users[i]; // ok, we have something that we can return
return User(); // unnatural: what user is that?
}
Why is that unnatural?
I only want to give something that I own. If that was possible, I could return a
const User&
instead of a fat copy of something that I artificially create (and destroy soon thereafter).If the caller wants to differentiate between “found” and “not found” (occasionally callers exhibit such desires), currently this has to be done by checking the validity of the returned object (using wrinkles such as
User::isvalid()
):User user = db.search_by_lastname("Faschingbauer"); if (user.isvalid()) { // do something with it } else { // error handling, possibly }
Exercise¶
Create a new file,
errors.h
(which will hold all future exception classes).In that file, implement (inline only) a custom exception,
class UserNotFound
(see here for how to create a custom exception).Modify
UserDB::search_by_lastname()
to throw an instance of it in the not-found case.Test this using the program below (feel free to use your own version of it):
#include "userdb.h"
#include <iostream>
int main()
{
UserDB db;
try {
User user = db.search_by_lastname("Faschingbauer");
// unreached because database is empty
std::cout << "yay!" << user.lastname() << std::endl;
return 0;
}
except (const UserNotFound& e) {
std::cerr << "argh: no \"Faschingbauer\" in there" << std::endl;
return 1;
}
}