The key reason this works is that for_each () doesn’t actually assume
its third argument to be a function.
It simply assumes that its third
argument is something that can be
called with an appropriate argument. 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 function.
Consequently, function objects often
execute faster than do ordinary
functions. An object of a class with
an application operator (§11.9) is
called a functionlike object, a
functor, or simply a function object.
[Stroustrup, C++ 3rd edition, 18.4-last paragraph]
I always thought that the operator
( ) call is just like function call
at runtime. how does it differ from
a normal function call?
Why is it easier to inline the
application operator than a normal
function?
How are they faster than function
call?
Generally, functors are passed to templated functions - if you're doing so, then it doesn't matter if you pass a "real" function (i.e. a function pointer) or a functor (i.e. a class with an overloaded operator()). Essentially, both have a function call operator and are thus valid template parameters for which the compiler can instantiate the for_each template. That means for_each is either instantiated with the specific type of the functor passed, or with the specific type of function pointer passed. And it's in that specialization that it is possible for functors to outperform function pointers.
After all, if you're passing a function pointer, then the compile-type type of the argument is just that - a function pointer. If for_each itself is not inlined, then this particular for_each instance is compiled to call an opaque function pointer - after all, how could the compiler inline a function pointer? It just knows its type, not which function of that type is actually passed - at least, unless it can use non-local information when optimizing, which is harder to do.
However, if you pass a functor, then the compile-time type of that functor is used to instantiate the for_each template. In doing so, you're probably passing a simple, non-virtual class with only one implementation of the appropriate operator(). So, when the compiler encounters a call to operator() it knows exactly which implementation is meant - the unique implementation for that functor - and now it can inline that.
If your functor uses virtual methods, the potential advantage disappears. And, of course, a functor is a class with which you can do all kinds of other inefficient things. But for the basic case, this is why it's easier for the compiler to optimize & inline a functor call than a function pointer call.
Summary
Function pointers can't be inlined since while compiling for_each the compiler has only the type of
the function and not the identity of the function. By contrast, functors can be inlined since even though the compiler only has the type of functor, the type generally suffices to uniquely identify the functor's operator() method.
Consider the two following template instantiations:
std::for_each<class std::vector<int>::const_iterator, class Functor>(...)
and
std::for_each<class std::vector<int>::const_iterator, void(*)(int)>(...)
Because the 1st is customised for each type of function object, and because operator() is often defined inline, then the compiler may, at its discretion, choose to inline the call.
In the 2nd scenario, the compiler will instantiate the template once for all functions of the same signature, therefore, it cannot easily inline the call.
Now, smart compilers may be able to figure out which function to call at compile time, especially in scenarios like this:
std::for_each(v.begin(), v.end(), &foo);
and still inline the function by generating custom instantiations instead of the single generic one mentioned earlier.
I always thought that the operator ( ) call is just like function call at runtime. how does it differ from a normal function call?
My guess is not very much. For evidence of this, look at your compiler's assembly output for each. Assuming the same level of optimization, it's likely to be nearly identical. (With the additional detail that the this pointer will have to get passed.)
Why is it easier to inline the application operator than a normal function?
To quote the blurb you quoted:
For example, it is easier to inline the application operator of a class than to inline a function passed as a pointer to function.
I am not a compiler person, but I read this as: If the function is being called through a function pointer, it's a hard problem for the compiler to guess whether the address stored in that function pointer will ever change at runtime, therefore it's not safe to replace the call instruction with the body of the function; come to think of it, the body of the function itself wouldn't necessarily be known at compile time.
How are they faster than function call?
In many circumstances I'd expect you wouldn't notice any difference. But, given your quotation's argument that the compiler is free to do more inlining, this could produce better code locality and fewer branches. If the code is called frequently this would produce notable speedup.
Related
There are two standard methods of passing arguments -- by value, and constant reference. Each has its trade-offs, with value being preferable in most cases that the data is very small. However, I just recently looked into templates more, and the way I understand it, they act more like a macro. Could you use templates to favor efficiency (disregarding bad code cleanliness for now)? For example, if I passed a std::vector through a template, would it allow access to the current scope to the function called?
I think you are misunderstanding what templates are.
Template arguments are not another way of passing runtime arguments to a function. Templates are a way essentially of doing code generation if you want to use the exact same code multiple times but with different types and/or constants when you know all the types and constant values at compile time.
So to answer your question
For example, if I passed a std::vector through a template, would it
allow access to the current scope to the function called?
you can't pass an std::vector value to a template function beyond normal argument passing which may be parametrized on the type. As for allowing access to a vector in the current scope, you don't need templates for that anyway: pass a reference to the vector.
I am unable to understand the difference between
Passing pointers as function arguments
Passing pointers as non type template parameter
Can you please help understand what optimization is achieved by choosing 2 (Particularly from the context of fast delegates as explained here and as used here)?
Some of my confusions surrounding the use of pointers as non type parameters are
When pointers are resolved at compile time how does the compiler know what the pointer is pointing to?
How is a member function pointer resolved at compile time when member functions can be virtual?
When pointers are resolved at compile time how does the compiler know what the pointer is pointing to?
Because that's how templates work. For all of their complexity, the basic idea of a template is very simple.
A template is a (smart) macro. When you instantiate a template, you are basically creating a copy of the template, where every use of the template parameters is replaced by the corresponding arguments passed at instantiation-time.
So this:
template<func_ptr ptr>
void func1();
{
ptr();
}
func1<some_func>();
Is functionally equivalent to this:
void func2()
{
some_func();
}
func2();
How does the compiler know that func2 will call some_func? Because that's literally what you wrote in the code. How does the compiler know that func1<some_func> will call some_func? Because that's literally what you wrote in the code when you named it func1<some_func>.
How is a member function pointer resolved at compile time when member functions can be virtual?
That all depends on what you mean by "resolved".
Assuming that the class the function is invoking the member pointer on is not final (you can't inherit from a final class, so the compiler knows exactly which function to call), the compiler cannot determine exactly which override will be called.
However, the compiler does know where that override is. Assuming we're talking about a vtable-based implementation of virtual functions, a member pointer contain an index into the vtable that the compiler would use to find the actual override function. But if the member pointer is known at compile time, that means the index is also known at compile-time. So the compiler need not dynamically index into the table; it can statically index it.
So in a way, it can be considered to have "resolved" the override at compile time. At least, to the extent possible.
Consider such a beast:
template<typename Func>
void register_function(Func func) {
// type-erase Func and pass it on to some other function
}
Assume that this can be passed anything callable.
I know how to get at the function's signature if Func is a plain function type. Given that func could be a plain function, a std::function<F>, or a function object (a std::bind() expression), how can I get at the function's arguments?
Note:
in this case, the functions only ever have either zero, one, or two arguments
if it's a function object, it's the result of std::bind()
the signature is needed in order to get at the argument's types, which need to be usable in the type-erased thing passed on
this is strictly C++03 (embedded platform), so no variable template arguments etc.
Impossible. A function object can have overloaded or templated operator(). Thus the idea of it having "a signature" simply doesn't apply, because it can have an unbounded number of signatures.
If you restrict it to only having one signature, then you can take the address of operator() and then get the arguments from the member function pointer type using regular template specialization.
If you know at runtime the signature of some called (plain) function, you could use (on Linux notably) the libffi to call it.
If you don't even know at runtime the signature of the function to call, it is impossible, since in general the ABI conventions will dictate different ways of passing function arguments according to their type.
For instance, the x86-64 ABI (followed on most Linux 64 bits x86-64 systems) requires that floating point values and integral values are passed in different set of registers.
See for example the x86 calling conventions wikipage.
I'm receiving the following warning:
warning: converting from 'void (MyClass::*)(byte)' to 'void (*)(byte)'
This is because I need to pass as argument a member function instead of an ordinary function. But the program is running correctly.
I'd like to disable this warning (Wno-bad-function-cast doesn't work for C++) or to implement a different way to pass a member function.
No. Take this warning seriously. You should rather change your code to handle this scenario.
Pointer to member function(void (MyClass::*)(byte)) and normal function pointer (void (*)(byte)) are entirely different. See this link. You cannot cast them just like that. It results in undefined behavior or crash.
See here, how they are different:
void foo (byte); // normal function
struct MyClass {
void foo (byte); // member function
}
Now you may feel that, foo(byte) and MyClass::foo(byte) have same signature, then why their function pointers are NOT same. It's because, MyClass::foo(byte) is internally resolved somewhat as,
void foo(MyClass* const this, byte);
Now you can smell the difference between them.
Declare pointer to member function as,
void (MyClass::*ptr)(byte) = &MyClass::foo;
You have to use this ptr with the object of MyClass, such as:
MyClass obj;
obj.*ptr('a');
You can't pass a function that takes two arguments to a place that expects a function that takes one. Can't be done, forget about it, period, end of story. The caller passes one argument to your function. It doesn't know about the second argument, it doesn't pass it to your function, you can't make it do what you want however hard you try.
For the very same reason you can't pass a non-static member function where a regular function is expected. A member function needs an object to operate on. Whatever code calls your function doesn't know about the object, there's no way to pass it the object, and there's no way to make it use the right calling sequence that takes the object into account.
Interfaces that take user's functions, without taking additional data that the user might want to pass to his function, are inherently evil. Look at the qsort() function from the C standard library. That's an example of an evil interface. Suppose you want to sort an array of string according to some collation scheme defined externally. But all it accepts is a comparison function that takes two values. How do you pass that collation scheme to your comparison function? You can't, and so if you want it working, you must use an evil global variable, with all the strings attached to it.
That's why C++ has moved away from passing function pointers around, and towards function objects. Function objects can encapsulate whatever data you want.
Also, this may be helpful
union FuncPtr
{
void (* func)(MyClass* ptr, byte);
void (MyClass::* mem_func)(byte);
};
I know that Function Templates are used so as to make the functions portable and so that they could be used with any data types.
Also Explicit Specialization of templates is done if we have a more efficient implementation for a specific data type.
But then instead of Explicit Specialization we could also just code a Nontemplate Function which could be called from main .
This would save us some processing time as the compiler would locate Nontemplate Functions faster than Explicitly Specialized Templated Functions which would in turn be better in terms of efficiency.
So why do we use Explicit Specialization when we have the alternative of just calling Nontemplate Functions?
Please correct me If I'm wrong!
Edit 1:
I was told by my professor that whenever we make function templates and call the function from main ,the compiler first looks for a templated function and if its not able to locate that,then it searches for a function template from which it in turn makes a templated function and then calls for it.
This would save us some processing time as the compiler would locate Global Functions faster than Explicitly Specialized Templated Functions which would in turn be better in terms of efficiency.
Why would the compiler find a nontemplate function faster than a function template specialization? Have you benchmarked compiler performance to verify this statement? If you use a function named f, the compiler always has to compile a set of candidate functions and perform overload resolution to determine the correct function to be used.
At runtime (which is when performance really matters, right?) the performance of calling a function template instantiation should be no better than the performance of calling a nontemplate function.
So why do we use Explicit Specialization when we have the alternative of just calling Global Functions?
In the general case, for function templates, you don't use explicit specialization, because it's usually confusing and difficult. The ISO C++ standard has a poetic warning to be extremely cautious when specializing function templates. You can read Herb Sutter's "Why Not Specialize Function Templates?" for a good explanation of the issues and why you don't want to specialize function templates.
It sounds like you're confusing compile-time efficiency with run-time efficiency. The choice of which function to call is made at compile time, not run time, so it will make no difference to the run time of the program.
Explicit Specialization is used when you have a special case that can benefit from special treatment. Sometimes this backfires, as in the case of std::vector<bool>, while other times it's quite handy. It means that the user of the function doesn't need to be aware that there's a special case; it's just transparent.
For reasons of uniformity. The person using the API just calls methods with particular arguments, some get the generic function some get explicitly specialised functions - the client need neither know nor care which they use.