I'd probably do this:
const SomeObject& SomeScope::ReturnOurObject()
{
if( ! SomeCondition )
{
throw SomeException();
}
return ourObject;
}
const SomeObject *SomeScope::ReturnOurObjectIfPermitted()
{
return SomeCondition ? &ourObject : 0;
}
And perhaps also:
bool SomeScope::CheckMode();
return SomeCondition;
}
Callers then have some options:
// 1 - "I know that I'm in the right mode"
myScope.ReturnOurObject().DoSomething();
// 2 - "I don't know whether I'm in the right mode, but I can cope either way"
if (SomeObject *myObject = myScope.ReturnOurObjectIfPermitted()) {
myObject->DoSomething();
} else {
DoSomethingElse();
}
// 2 - alternate version:
if (myScope.CheckMode()) {
SomeObject &myObject = myScope.ReturnOurObject();
myObject.DoSomething();
} else {
DoSomethingElse();
}
// 3 - "I don't know whether I'm in the right mode. If I'm not then
// I can't deal with it now, but some higher-level code can"
try {
// ... several calls deep ...
myScope.ReturnOurObject().DoSomething();
// ... several returns back ...
} catch (SomeException &e) {
DoSomethingElse();
}
You design a function's interface differently according to what the preconditions are, i.e. whose responsibility it is to ensure it can do its job.
If it's the caller's responsibility, then they need the ability to ensure that. You might want to check anyway, just to be on the safe side. Throwing an exception when the so-called "preconditions" aren't met makes them more like advice than conditions, and it can work quite well provided you don't mind the runtime overhead of checks everywhere. I'm usually fairly unforgiving with preconditions, so actually I might replace the conditional exception with an assert, and document that the function must not be called in the wrong mode. It depends how much control the caller has over the mode - obviously if it changes arbitrarily (e.g., if "SomeCondition" is "there is not a byte available on the UART") then you need a very different interface from if it only ever changes when the client code calls some function to change it.
If it's not the caller's responsibility to get the mode right, then your interface shouldn't write cheques that your implementation can't cash. In this case if it's "expected" that there will be no object to return, then the return should not be by reference. Unless either (a) you can rustle up a special "sorry, it didn't work" object to return, that the caller can check for, or (b) you're comfortable throwing exceptions in "expected" situations. IMO (b) is rare in C++. (a) usually isn't any better than returning a null pointer, but occasionally it is. For instance returning an empty collection to mean "there's nothing you're allowed to see here" might result in some very clean calling code, if DoSomethingElse()
would have been "do nothing". So as well as the desired responsibilities, the interface depends on the expected use cases.