C++ Function passed as Template Argument vs Parameter - c++

In C++, there are two ways of passing a function into another function that seem equivalent.
#include <iostream>
int add1(int i){ return i+1; }
int add2(int i){ return i+2; }
template <int (*T)(int) >
void doTemplate(int i){
std::cout << "Do Template: " << T(i) << "\n";
}
void doParam(int i, int (*f)(int)){
std::cout << "Do Param: " << f(i) << "\n";
}
int main(){
doTemplate<add1>(0);
doTemplate<add2>(0);
doParam(0, add1);
doParam(0, add2);
}
doTemplate accepts a function as a template argument, whereas doParam accepts it as a function pointer, and they both seem to give the same result.
What are the trade-offs between using each method?

The template-based version allows the compiler to inline the call, because the address of the function is known at compile-time. Obviously, the disadvantage is that the address of the function has to be known at compile-time (since you are using it as a template argument), and sometimes this may not be possible.
That brings us to the second case, where the function pointer may be determined only at run-time, thus making it impossible for the compiler to perform the inlining, but giving you the flexibility of determining at run-time the function to be called:
bool runtimeBooleanExpr = /* ... */;
doParam(0, runtimeBooleanExpr ? add1 : add2);
Notice, however, that there is a third way:
template<typename F>
void doParam(int i, F f){
std::cout << "Do Param: " << f(i) << "\n";
}
Which gives you more flexibility and still has the advantage of knowing at compile-time what function is going to be called:
doParam(0, add1);
doParam(0, add2);
And it also allows passing any callable object instead of a function pointer:
doParam(0, my_functor());
int fortyTwo = 42;
doParam(0, [=] (int i) { return i + fortyTwo; /* or whatever... */ }
For completeness, there is also a fourth way, using std::function:
void doParam(int x, std::function<int(int)> f);
Which has the same level of generality (in that you can pass any callable object), but also allows you to determine the callable object at run-time - most likely with a performance penalty, since (once again) inlining becomes impossible for the compiler.
For a further discussion of the last two options, also see this Q&A on StackOverflow.

Template parameters
have to be known at compile time.
lead to one function instantation for every distinct value of the parameter (so-called template bloat)
the called function is transparant to the compiler (inlining, but could lead to even more bloat, double-edged sword)
the calling function can be overloaded for particular values of the parameter, without modifying existing code
Function pointers
are passed at run time.
only lead to one calling function (smaller object code)
the called function is typically opaque to the compiler (no inlining)
the calling function needs a runtime if/switch to do special stuff for special values of the parameter, this is brittle
When to use which version: if you need speed and a lot of customization, use templates. If you need flexibility at runtime, but not in the implementation, use function pointers.
As #AndyProwl points out: if you have a C++11 compiler, function pointers are generalized to callable objects such as std::function and lambda expressions. This opens up a whole new can of worms (in a good sense).

Related

When to return T&& from a non-template and non-member function

Please note that there are previous answers concerning template functions or member functions but this question is only about non-template non-member functions. std::move() returns T&&, for example but it is a template function.
Is there ever a good reason to use T&& as a return type from a non-template and non-member function, where T is any arbitrary type?
For example when would you ever use the following?
T&& fn()
{
....
return ....
}
I have seen examples where this is used but in all the examples, the developer misunderstood move semantics and should have returned by value and taken advantage of NRVO.
Suppose we were to have a particle system. We want to implement this as a pool of particles. This means that we are going to want to recycle the same particles over and over again, so to reuse resources, we will want to pass around rvalues.
Now, suppose that our particles have a very short life time, but we want something to happen when they "expire" (like incrementing an integer x) but we still want to recycle them. Now, suppose that we want to be able to specify x. But, now what do we do?
On move, we want to be able to call a function to increment a variable, but that variable must fluctuate. We wouldn't want to put this into a destructor because this would involve either templates to derive the exact function call at compile time or we would need a std::function or function pointer to refer to the function from inside a particle, wasting space. What we want to do is to be able to take in an expiring value, do an action, and then forward it. In other words, we want an outgoing-move with a side effect specifically on the conversion from lvalue to rvalue.
It does matter on which action you do it--on lvalue to rvalue conversion or on receiving an into another Particle with operator= or operator(). Either you do it when an object receives a value or when you take the rvalue in. But suppose we want to do this for many different types of objects--do you want to write 5 or more different move functions for each of 5 different classes, or perhaps should we parameterize over the types with a external templated function?
How else would you do this? You're still going to use std::move() from inside the object, but we want to couple it with a function external to the object, because this would represent a side effect with a move.
Coliru: http://coliru.stacked-crooked.com/a/0ff11890c16f1621
#include <iostream>
#include <string>
struct Particle {
int i;
};
template <typename T>
T&& move( T& obj, int (*fn)(int) , int& i ) {
i = fn(i);
return(std::move(obj));
}
int increment(int i) { return i+1; }
int main() {
// Have some object pool we want to optimize by moving instead of creating new ones.
// We'll use rvalue semantics so we can "inherit" lifetime instead of copying.
Particle pool[2000];
// Fill up the "particles".
for (auto i = 0; i < 2000; ++i) {
pool[i].i = i;
}
// Perform the moves with side effects.
int j = 0;
for (auto i = 0; i < 1999; ++i) {
pool[i+1] = move<Particle>(pool[i], &increment, j);
std::cout << "Moves performed: " << j << '\n';
}
}
Sometimes, it would be handy to have a method that returns *this as an l-value reference, so that you can pass a temporary to a function that accepts an l-value reference.
func(foo_t().lval_ref());
So, why would people want to do this? Suppose a function takes an l-value reference as an output variable. If the caller does not actually need this output, it would be convenient to pass a temporary instead of defining some dummy variable unused, and then static_cast<void>(unused); to suppress any warnings of unused variable.
Similarly, one may want to have a method that returns *this as an r-value reference, which is used the same way as std::move(). Doing this allows you greater flexibility. You can do any tricky things you want within the method implementation :-)

Why must function pointers be used?

What is the need for function pointers? The standard answer for this seems to be callbacks, but why can't we just pass a function?
The book I was reading on C++ demonstrates passing a function as a parameter, and acknowledges that in actual fact the compiled turns this into a function pointer and passes that instead, because functions are not actual objects. It showed the equivalent code using function pointers, which was slightly more complex - if the code is equivalent, why bother to use a function pointer.
I presume there is a case when is simply isn't possible to pass the function, and one must pass a pointer instead? Can someone give me an example of this case, as it would help me understand why function pointers are useful.
Consider the following code:
#include <iostream>
using namespace std;
int add(int x) {
return ++x; //this is a copy, so it doesn't touch x
}
void runprint(int function(int x), int x) {
cout << function(x) << endl;
}
int main() {
runprint(add, 1);
return 0;
}
We are passing a function as a parameter, not a pointer. The function accepting the function (!), is not accepting a pointer.
TL; DR
"Function" and "pointer to function" is the same.
There is the concept of a pointer, and the syntax of its usage; it's not clear what you are asking about.
Concept
A pointer to a function may be different from the function itself (the difference is not useful in c++ - see below) in that a function may occupy much space - its code can be arbitrarily complex. Manipulating (e.g. copying or searching/modifying) the code of a function is rarely useful, so c/c++ don't support it at all. If you want to modify the code of a function, cast a pointer to char*, applying all the necessary precautions (I have never done it).
So if you are writing C, all you need is pointers to functions.
However...
Syntax
If you have a pointer p to a function, how do you want to call the function?
(*p)(18); // call the function with parameter 18
p(18); // the same, but looks better!
There is the slightly cleaner syntax not involving the * sign. To support it, the authors of c/c++ invented the concept of "decay" - when your code mentions "a function", the compiler silently "corrects" it to mean "a pointer to a function" instead (in almost all circumstances; excuse me for not detailing further). This is very similar to the "decay" of an array to a pointer mentioned by vsoftco.
So in your example
void runprint(int function(int x), int x) {
cout << function(x) << endl;
}
the "function" type is actually a "pointer to function" type. Indeed, if you try to "overload":
void runprint(int (*function)(int x), int x) {
cout << function(x) << endl;
}
the compiler will complain about two identical functions with identical set of parameters.
Also, when making a variable of a function / pointer-to-function type
runprint(add, 1);
it also doesn't matter:
runprint(&add, 1); // does exactly the same
P.S. When declaring a function that receives a callback, I have mostly seen (and used) the explicitly written pointer. It has only now occurred to me that it's inconsistent to rely on function-to-pointer decay when calling the callback, but not when declaring my code. So if the question is
why does everyone declare callbacks using a pointer-to-function syntax, when a function syntax would be sufficient?
I'd answer "a matter of habit".
function is considered a function pointer by g++:
$ cat fp.cpp
#include <typeinfo>
#include <iostream>
using namespace std;
int add(int x) {
return ++x; //this is a copy, so it doesn't touch x
}
void runprint(int function(int x), int x) {
cout << typeid(function).name() << endl;
int (*f)(int); // function pointer compatible with function argument
f = function;
cout << typeid(f).name() << endl;
cout << function(x) << endl;
}
int main() {
runprint(add, 1);
return 0;
}
$ g++ -Wall -std=c++11 -o fp fp.cpp
$ ./fp
PFiiE
PFiiE
2
Function pointer is a pointer that holds the address of the function.
Function pointer is to invoke the function even if the name of the function is unknown. This is practical in using different function at runtime.

Using the same instance of an object as the argument and as the calling object in calling a function

I wrote a small program for an assignment in an object-oriented C++ class in which I had to write a function which displayed the magnitude of a complex number. It works when written this way and I know how to write it without arguments in the parameter, but I want to know if there is a functional problem with the code (the calling object and the argument are the same object).
// displays the magnitude of a complex number
void Complex::magnitude(Complex c) const {
cout << "\nMagnitude of "; c.display(); cout << " = ";
cout.precision(3); cout.setf(std::ios::fixed, std::ios::floatfield);
cout << sqrt(pow(static_cast<double>(c.real), 2) +
(pow(static_cast<double>(c.imag), 2)) ) << "\n";
} // end function magnitude
Here's the redundant part with c1 as the calling object and argument:
c1.magnitude(c1);
I know how to write this code without c1 as an argument for magnitude() and that all I have to do is delete the argument and delete "c." from the function and it will still work the same. My question is simply Is this be a problem functionally when a program is written like this?
Your code makes syntactically no sense. Either use a member function taking no argument, or a free-standing function with argument (or both).
namespace My {
struct Complex {
void magnitude() const; // member function
...
};
void magnitude(Complex const&); // free-standing function
}
These can be used like this
My::Complex c1;
c1.magnitude();
magnitude(c1);
(However, using the name magnitude for a function not returning the magnitude is dangerous and therefore bad practice, better call it print_magnitude_to_stdout().)
This will not be a problem functionally, but logically if the function must take an object as an argument, you should make this function static.
In addition, since you are not modifying the incoming object, you should make the argument const. Finally, since copying the object may be more expensive than copying a reference, you may want to change the argument to be passed by reference.
static void Complex::magnitude(const Complex &c);
...
Complex myComplex(...);
Complex::magnitude(myComplex);
Functionally your code is OK, with one caveat: your function takes its argument by value, and therefore relies on the copy constructor. If the copy ctor is fine, your code is fine; otherwise, it may not be.
Stylistically, I find this code objectionable. It should either be a parameterless member function, or a one-argument static function (taking its argument by const reference).

Why do two functions have the same address?

Consider this function template:
template<typename T>
unsigned long f(void *) { return 0;}
Now, I print the addresses of f<A> and f<B> as:
std::cout << (void*)f<A> << std::endl;
std::cout << (void*)f<B> << std::endl;
Why do they print the same address if compiled in MSVS10? Are they not two different functions and therefore should print different addresses?
Updated:
I realized that on ideone, it prints the different address. MSVS10 optimizes the code, as the function doesn't depend on T in any way, so it produces same function. #Mark's answer and comments on this are valuable. :-)
You need to cast to void *:
std::cout << (void*)(ftype*)f<A> << std::endl;
std::cout << (void*)(ftype*)f<B> << std::endl;
If you cast to a function pointer (or several other classes of non-void pointers), it will be interpreted as a bool by the operator<< for std::ostream (hence the 1).
Since the function doesn't depend on the template parameter, the compiler can condense all instantiations into a single function.
I don't know why you get 1 for the address.
Added by Nawaz:
I experimented with my real code, and concluded that what #Mark said above is very important here :
Since the function doesn't depend on the template parameter, the compiler can condense all instantiations into a single function.
I also came to a conclusion that if the function-body depends on T*, not on T, it still produces the same function for different type arguments in my real code (not on ideone, though). However, if it depends on T, then it produces different functions, because sizeof(T) differs (fortunately for me) for different type arguments.
So I added a dummy automatic variable of type T in the function template, so that the function could depend on the size of T so as to force it to produce different functions.
This is simply a case of undefined behavior because the results of casting a pointer to a function to a pointer to object type are undefined.
A more interesting expression to examine would bef<A> == f<B> which should evaluate to true if and only if A and B refer to the same type.

Function References

So I was just working with function pointers and I remembered that you could do this:
void Foo()
{
}
int main()
{
void(& func)() = Foo;
func(); //::Foo();
}
The obvious advantage being that references reference valid objects (unless they're misused), or functions in this case.
The obvious disadvantages being that you can't store an array of references and can't use them for member function pointers (at least as far as I can tell).
My question: does anyone use them (i.e., function references, not function pointers), and if so, in what scenarios have you found them useful/helpful?
The only place I can see them being useful off the bat is binding a reference to a certain function when working with conditional compilation.
I've used them before to add customization to classes by passing them to the constructor in a way like the strategy pattern
Function references, unlike function pointers, make it harder to create them from an invalid source. This is useful if you are making a wrapper around a C library - the C++ code can take a callback function by reference and pass the pointer to the C library if the lbrary requires that the passed pointer must not be NULL.
It is also a convenient way to alias a function, especially in C++11 with the new auto keyword:
#include <iostream>
#include <typeinfo>
void f(int i, char c)
{
std::cout << i << ' ' << c << std::endl;
}
int main()
{
std::cout << typeid(f).name() << std::endl; //FvicE
f(0, '1');
void (*pf)(int, char) (&f); //ugly
std::cout << typeid(pf).name() << std::endl; //PFvicE
(*pf)(2, '3');
pf(4, '5'); //works, but I don't recommend it
void (&rf)(int, char) (f); //still ugly
std::cout << typeid(rf).name() << std::endl; //FvicE
rf(6, '7');
auto &af (f); //pretty, but only works in C++11
std::cout << typeid(af).name() << std::endl; //FvicE, same as above
af(8, '9');
}
I think your example usage is quite good. Because if you would use an ordinary function pointer, and you then apply the address-of operator, you would get the address of the function pointer. Using a reference to function will do the expected thing, in that it returns a pointer to the function itself.
I also can't think of many examples. Keeping function references, as you point out, has some ugly consequences. Another possibly unwanted consequence is, if kept as a class-member, your objects will be non-assignable if you don't write your own operator= and refrain from trying to re-assign the function-reference.
I think most uses of function references are implicit, much like most uses of array-references - although much more so, when you accept arguments by-reference:
template<typename T>
void do_something(T const& t) { ... }
While accepting arrays by reference has the advantage of not losing their size information, accepting functions by reference explicitly doesn't seem to have an advantage (at least as far as I can see). I suppose the existence of function references largely is justified by the idealistic view of a reference as an alias-name of some object or function, together with the fact that it allows passing functions to such templates that accept their argument by reference.
I would probably avoid using them if I wouldn't need them inevitably. Constant function pointers also provide non-reassignable callables, and will probably avoid confusions when other programmers, who possibly are not very familiar with this language niches, read your code. Worth to note that Vandervoorde & Josuttis also recommend to avoid them to reduce confusion (in their book C++ Templates - The Complete Guide).
in addition to the use as strategy (as pointed out by Robert Gould), I freqently use them at the entrance point to (template) metaprogramming. A function reference can easily be picked up by a template parameter; from this point on it can be passed through several layers of (metaprogramming) templates. Of course, this holds true for a function pointer as well, but the reference is an alias and thus communicates the intention more clearly.
To give an example: when writing a generic command dispatching system for an application, a lot of different operations need to be announced as commands. We can use a simple "builder function" as front-end for the client code. Behind the scenes, this builder function picks up the actual function signature as template parameter, derives (by template metaprogramming) the actual parameter and return type values and possibly picks the suitable specialisation to store a "memento" and an "undo functor". These functors can than be stored either as function pointers internally, or using boost or tr1 or C++11 function objects. This way, it is possible to build a type safe command invocation and "undo" system.
I've used them in a plug-in system where plug-in DLLs could be loaded/unloaded at run-time. I would look for known symbols in each DLL and cast them to function pointers.