Will this be hard/expensive to inline?

  • Thread starter Steven T. Hatton
  • Start date
S

Steven T. Hatton

I don't really understand the details of what happens when a compiler
inlines a given function. I know that basically it's supposed to cause the
function to be placed directly on the stack per invocation (or something
like that.) That would be in contrast to loading one instance of the
function and branching to it each time.

I don't believe that means I would have a separate instance of a member
function loaded per object instance. But I would like some verification in
this regard.

I'm wondering what the consequences of having the default case throw the
exception indicated in the following code:

template <typename T>
inline T Vector3<T>::eek:perator[](const unsigned& index) const
throw (out_of_range)
{
switch(index){
case 0: return _v[0];
case 1: return _v[1];
case 2: return _v[2];
default:
std::stringstream ss;
ss << namespace_name + "::"
<< class_name
<< "::eek:perator[" << index <<"]";
throw out_of_range(ss.str());
}
}

Could that impact the ability of the compiler to inline the function, or
cause significant bloat if it were inlined?

I also wonder about the performance hit I take by using the switch
statement. I believe this boils down the fact that I can't both have my
cake (ideal performance) and eat it(checked access.) Is this really a case
of either/or? Could I reasonably expect a compiler to optimize away the
comparison for index values 0,1,2?
--
"If our hypothesis is about anything and not about some one or more
particular things, then our deductions constitute mathematics. Thus
mathematics may be defined as the subject in which we never know what we
are talking about, nor whether what we are saying is true." - Bertrand
Russell
 
G

Gianni Mariani

Steven said:
I don't really understand the details of what happens when a compiler
inlines a given function.


It's implementation dependant.

....
I'm wondering what the consequences of having the default case throw the
exception indicated in the following code:

template <typename T>
inline T Vector3<T>::eek:perator[](const unsigned& index) const
throw (out_of_range)
{
switch(index){
case 0: return _v[0];
case 1: return _v[1];
case 2: return _v[2];
default:
std::stringstream ss;
ss << namespace_name + "::"
<< class_name
<< "::eek:perator[" << index <<"]";
throw out_of_range(ss.str());
}
}

This would probably be better:

template <typename T>
inline T & Vector3<T>::eek:perator[](const unsigned& index)
{
if ( index > 2 ) // index is unsigned so it can't be less than 0
{
IsBadIndex( class_name, index );
assert( false ); // should never get here
}
return _v[ index ];
}

template <typename T>
inline const T & Vector3<T>::eek:perator[](const unsigned& index) const
{
if ( index > 2 ) // index is unsigned so it can't be less than 0
{
IsBadIndex( class_name, index );
assert( false ); // should never get here
}
return _v[ index ];
}

And don't inline IsBadIndex ...
Could that impact the ability of the compiler to inline the function, or
cause significant bloat if it were inlined?

I also wonder about the performance hit I take by using the switch
statement. I believe this boils down the fact that I can't both have my
cake (ideal performance) and eat it(checked access.) Is this really a case
of either/or? Could I reasonably expect a compiler to optimize away the
comparison for index values 0,1,2?

My experience with optimizers is that they do a good job with conditionals.
 
D

David Hilsee

Steven T. Hatton said:
I don't really understand the details of what happens when a compiler
inlines a given function. I know that basically it's supposed to cause the
function to be placed directly on the stack per invocation (or something
like that.) That would be in contrast to loading one instance of the
function and branching to it each time.

I don't believe that means I would have a separate instance of a member
function loaded per object instance. But I would like some verification in
this regard.

The keyword "inline" expresses the programmer's desire to have the
function's body inserted into the caller's body, eliminating the overhead
that can be associated with a function call. It has little to do with the
number of instances of an object. If some functions call a function X total
times, and that called function is inlined in every caller, then you would
have X copies of that function.
I'm wondering what the consequences of having the default case throw the
exception indicated in the following code:

template <typename T>
inline T Vector3<T>::eek:perator[](const unsigned& index) const
throw (out_of_range)
{
switch(index){
case 0: return _v[0];
case 1: return _v[1];
case 2: return _v[2];
default:
std::stringstream ss;
ss << namespace_name + "::"
<< class_name
<< "::eek:perator[" << index <<"]";
throw out_of_range(ss.str());
}
}

Could that impact the ability of the compiler to inline the function, or
cause significant bloat if it were inlined?
<snip>

Well, as it has already been said, this is all depends on the
implementation. But I think it's worth noting that you are using an
exception specification, which is something that most experts do not
recommend you do. Sutter says that you shouldn't bother to write them
(http://www.gotw.ca/gotw/082.htm). The boost "exception specification
rationale" (http://www.boost.org/more/lib_guide.htm#Exception-specification)
mentions that some compilers turn off inlining if there is an exception
specification.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,997
Messages
2,570,239
Members
46,827
Latest member
DMUK_Beginner

Latest Threads

Top