Reputation: 783
NodeModularStructureBuilder::NodeSetT const&
NodeModularStructureBuilder::GetSimilarNodesAtLevel ( Node const* p_node,
size_t level )
{
if ( p_node ) {
string s_name = StructuralAnalysis::Util::GetNLevelModularName (
p_node, level );
return this->node_ms_map_[s_name]; // this return is fine...
}
// if p_node is NULL then throw exception
throw Except::NullPointerCrash ( "Invalid node pointer passed to "
"FlopModularStructureBuilder::GetSimilarNodesAtLevel "
"output is not usable." );
// return ??????????
}
Q1. To avoid compiler error we need to return something from above function. what should we return? or suggest me how you handle return value of a member function (on an exception) which returns a reference?
Q2. Will program execution ever hit this return statement?
Upvotes: 1
Views: 133
Reputation: 55897
I think, that most simple way will be simply throw exception by condition.
if (!p_node)
{
throw Except::NullPointerCrash ( "Invalid node pointer passed to "
"FlopModularStructureBuilder::GetSimilarNodesAtLevel "
"output is not usable." );
}
string s_name = StructuralAnalysis::Util::GetNLevelModularName (
p_node, level );
return this->node_ms_map_[s_name]; // this return is fine...
also you can use some null object, or something like boost::optional
. But anyway, nothing after unconditional throw will be executed, so, there is no error in your code.
n3376 15.1/2
When an exception is thrown, control is transferred to the nearest handler with a matching type (15.3); “nearest” means the handler for which the compound-statement or ctor-initializer following the try keyword was most recently entered by the thread of control and not yet exited
Upvotes: 4
Reputation: 23324
Q1: you don't need to return anything when you throw. Your code should compile without errors.
Q2: No. Most compilers would issue an "Unreachable Code" warning.
Upvotes: 4
Reputation: 15210
In this case you can easily invert the condition:
NodeModularStructureBuilder::NodeSetT const&
NodeModularStructureBuilder::GetSimilarNodesAtLevel ( Node const* p_node,
size_t level )
{
if ( ! p_node ) {
// if p_node is NULL then throw exception
throw Except::NullPointerCrash ( "Invalid node pointer passed to "
"FlopModularStructureBuilder::GetSimilarNodesAtLevel "
"output is not usable." );
}
string s_name = StructuralAnalysis::Util::GetNLevelModularName (
p_node, level );
return this->node_ms_map_[s_name]; // this return is fine...
}
The other solution when you can not do something that simple is to use a fake NullObject. But as the code after the throw will never be called, it is somehow a waste. The NullObject pattern is useful to know, anyway.
Upvotes: 0
Reputation: 129524
When you throw
, the the function doesn't return anything - any code after throw
will not be executed, so there is no point in writing any code there. (As suggested in the other answer, reversing the condition, and throwing before a return
would be a solution to avoid compiler warnings/errors).
Obviously, the calling code will need to care for "not using the value stored from the return value", but in this case that shouldn't be a problem, as this looks like a direct "Oops" type error - in other words, no point in continuing. However if you have something like this:
std::String s;
try
{
for(;;)
{
s = readLineFromFile();
}
}
catch (...)
{
....
}
... use s
you'd be in trouble, because s
may not be the value you expect...
Upvotes: 4