Есть несколько методов.
1) Брось исключение. Это полезно, если вы хотите, чтобы GetAccountById
возвращал учетную запись по значению , а использование исключений соответствует вашей модели программирования. Некоторые скажут вам, что исключения «предназначены» для использования только в исключительных случаях. Такие вещи, как «не хватает памяти» или «компьютер в огне». Это очень спорно, и для каждого программиста вы найдете, кто говорит, что исключения не для управления потоком данных вы найдете другие (я в том числе), который говорит, что исключения могут быть использованы для управления потоком. Вам нужно подумать об этом и решить для себя.
Account GetAccountById(unsigned int id) const
{
if( account_not_found )
throw std::runtime_error("account not found");
}
2) Не возвращать и Account
по значению. Вместо этого вернитесь по указателю (желательно умному указателю) и верните NULL, если вы не нашли учетную запись:
boost::shared_ptr<Account> GetAccountById(unsigned int id) const
{
if( account_not_found )
return NULL;
}
3) Вернуть объект с флагом присутствия, указывающим, присутствует ли элемент данных. Boost.Optional является примером такого устройства, но в случае, если вы не можете использовать Boost, это шаблонный объект, который имеет bool
член, равный true
, когда присутствует элемент данных, и false
, когда это не так. Сам элемент данных хранится в элементе value_
. Должно быть конструируемым по умолчанию.
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_;
};
Для простоты я бы создал typedef для Account
:
typedef PresenceValue<Account> p_account;
... и затем верните это из вашей функции:
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
}
Использовать это просто:
p_account acct = FindAccountById(some_id);
if( acct.present_ )
{
// magic happens when you found the account
}