There are several methods.
1) Throw an exception. This is useful if you want GetAccountById
return an account by value, and using exceptions is appropriate for your programming model. Some will tell you that exceptions are "intended" for use only in exceptional circumstances. Things like “out of memory” or “computer on fire”. This is very controversial, and for each programmer you will find who says that exceptions are not for controlling the flow of data, you will find others (including myself), which says that exceptions can be used for controlling the flow. You need to think about it and decide for yourself.
Account GetAccountById(unsigned int id) const { if( account_not_found ) throw std::runtime_error("account not found"); }
2) Do not return and Account
by value. Instead, return the pointer (preferably a smart pointer) and return NULL when you did not find the account:
boost::shared_ptr<Account> GetAccountById(unsigned int id) const { if( account_not_found ) return NULL; }
3) Return an object that has a presence flag indicating whether a data item is present. Boost.Optional is an example of such a device, but if you cannot use Boost here, it is a template object with bool
member true
when the data element is present, and false
when it is absent. The data element itself is stored in the value_
element. It should be constructive by default.
template<class Value> struct PresenceValue { PresenceValue() : present_(false) {}; PresenceValue(const Value& val) : present_(true), value_(val) {}; PresenceValue(const PresenceValue<Value>& that) : present_(that.present_), value_(that.value_) {}; explicit PresenceValue(Value val) : present_(true), value_(val) {}; template<class Conv> explicit PresenceValue(const Conv& conv) : present_(true), value_(static_cast<Value>(conv)) {}; PresenceValue<Value>& operator=(const PresenceValue<Value>& that) { present_ = that.present_; value_ = that.value_; return * this; } template<class Compare> bool operator==(Compare rhs) const { if( !present_ ) return false; return rhs == value_; } template<class Compare> bool operator==(const Compare* rhs) const { if( !present_ ) return false; return rhs == value_; } template<class Compare> bool operator!=(Compare rhs) const { return !operator==(rhs); } template<class Compare> bool operator!=(const Compare* rhs) const { return !operator==(rhs); } bool operator==(const Value& rhs) const { return present_ && value_ == rhs; } operator bool() const { return present_ && static_cast<bool>(value_); } operator Value () const; void Reset() { value_ = Value(); present_ = false; } bool present_; Value value_; };
For simplicity, I will create a typedef for Account
:
typedef PresenceValue<Account> p_account;
... and then return this from your function:
p_account GetAccountByIf(...) { if( account_found ) return p_account(the_account); // this will set 'present_' to true and 'value_' to the account else return p_account(); // this will set 'present_' to false }
Using this is simple:
p_account acct = FindAccountById(some_id); if( acct.present_ ) { // magic happens when you found the account }
John dibling
source share