inlining function objects

G

Gianni Mariani

glen_stark said:
Hi.

I'm just curious if there any warnings or caveats or whatever to be
aware of when inlining function object calls? If the answer is no, they
inline just like everything else, that's good news for me.

I suspect you mean "member function" in the place of "function object
calls".

This is an implementation detail. You'll need to check your specific
compiler.

Having said that, most (if not all) implementations don't have any
constraints in this area that I have seen.
 
R

Rolf Magnus

glen_stark said:
Hi.

I'm just curious if there any warnings or caveats or whatever to be
aware of when inlining function object calls? If the answer is no,
they inline just like everything else, that's good news for me.

Actually, one reason to use function objects is because can be inlined
in some situations where normal functions can't.
 
M

Mike Wahler

Rolf Magnus said:
Actually, one reason to use function objects is because can be inlined
in some situations where normal functions can't.

Could you show a specific example please?

-Mike
 
G

glen_stark

Hi.

I'm just curious if there any warnings or caveats or whatever to be
aware of when inlining function object calls? If the answer is no, they
inline just like everything else, that's good news for me.

glen
 
D

David Harmon

Could you show a specific example please?

template <typename F>
void callfun(F *f)
{
(*f)();
}

Now, if you pass a function to this, the function to be called is (*f)
and only by dereferencing the pointer passed can the generated code call
the function.

But, if you pass a functional object the function to be called is
sometype::eek:perator() regardless of the pointer value, and the call can
probably be inlined.
 
A

Andrey Tarasevich

David said:
template <typename F>
void callfun(F *f)
{
(*f)();
}

Now, if you pass a function to this, the function to be called is (*f)
and only by dereferencing the pointer passed can the generated code call
the function.

But, if you pass a functional object the function to be called is
sometype::eek:perator() regardless of the pointer value, and the call can
probably be inlined.
...

This is not a fair comparison. The above version of the code is run-time
parametrized and the call cannot be resolved at compile time (which
prevents inlining). The functional object version is compile-time
parametrized, which makes inlining possible.

Run-time parametrization can be implemented with both ordinary functions
and functional objects (through virtual functions). In both cases
inlining is impossible.

Compile-time parametrization can also be implemented with both ordinary
functions and functional objects. In both cases inlining is possible.

Both run-time and compile-time parametrization has its own uses and its
own advantages/disadvantages.

In order to make fair comparison in our case, you have to make "ordinary
function" version compile-time parametrized. For example, like this

template <char (*F)(int)> char callfun(int i)
{
return F(i);
}

Function call can be inlined in this case.
 
R

Rolf Magnus

Andrey said:
This is not a fair comparison. The above version of the code is
run-time parametrized and the call cannot be resolved at compile time
(which prevents inlining). The functional object version is
compile-time parametrized, which makes inlining possible.

Right. But often, you don't actually need the run-time parametrization,
but still are forced to pay the penalty. Think of std::sort with a
custom comparison function.
Run-time parametrization can be implemented with both ordinary
functions and functional objects (through virtual functions). In both
cases inlining is impossible.
Right.

Compile-time parametrization can also be implemented with both
ordinary functions and functional objects. In both cases inlining is
possible.
Both run-time and compile-time parametrization has its own uses and
its own advantages/disadvantages.

In order to make fair comparison in our case, you have to make
"ordinary function" version compile-time parametrized. For example,
like this

template <char (*F)(int)> char callfun(int i)
{
return F(i);
}

Function call can be inlined in this case.

Hm, do any compilers actually do that? Anyway, none of the standard
library algorithms are using this, so you either have to use funciton
objects or go without inlining.
 
T

Tom

Mike Wahler said:
Could you show a specific example please?

inline bool isLess(int a, int b)
{
return a < b;
}

template<class T>
struct Less : public binary_function<T, T, bool> {
bool operator()(const T& t1, const T& t2) const
{
return t1 < t2;
}
};

std::sort(vec.begin(), vec.end(), isLess); // #1

vs.

std::sort(vec.begin(), vec.end(), Less<int>()); // #2

This is an implementation detail, but for most implementations in
wide-use today, #1 will not be inlined, but #2 will. I've confirmed
this on VC++.net and gcc 3.3.2. Try it for yourself and see.

Also, take a look at the following sources:

"Function objects are usually faster than ordinary functions. The
concept
of templates usually allows better optimization because more details
are
defined at compile time. Thus passing function objects instead of
ordinary
functions [to Standard Library algorithms] often results in better
performance." Josuttis, C++ Standard Library, Sec. 5.9, p. 127.

"A suitably-defined object serves as well as - and often better than -
a
function. For example, it is easier to inline the application
operator of a
class than to inline a function passed as a pointer to a function.
Consequently, function objects often execute faster than do ordinary
functions." Stroustrup, TC++PL (3d. ed.), Sec. 18.4, p. 515.

"Interestingly, if you were to compare the performance of the two
calls to
sort (one using greater<double>, one using doubleGreater [an ordinary
function declared inline]), you'd almost certainly find that the one
using
greater<double> was faster. For instance, I timed the two calls to
sort on
..... four different STL platforms, each set to optimize for speed, and
the
version using greater<double> was faster every time. . . . Because
[doubleGreater] is a pointer to a function, each time it's used inside
sort,
compilers make an indirect function call. . . . Most compilers won't
try to
inline calls to functions that are invoked through function pointers,
even
if, as in this example, such functions have been declared inline and
the
optimization appears to be straightforward." Meyers, Effective STL,
Item
46, pps. 202-03.

There was a thread on this clc++m last month:

http://groups.google.com/[email protected]&frame=off

Best regards,

Tom
 

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,755
Messages
2,569,536
Members
45,008
Latest member
HaroldDark

Latest Threads

Top