Pointer to a procedure - c++

Does it possible to invoke a procedure via pointer? I haven't found anything about it on the internet, but the following experimental code compiles without warnings.
#include <iostream>
#include <ctime>
using namespace std;
void PrintCurrentClock()
{
cout<<clock()<<endl;
}
void PrintCurrentTimeStamp()
{
cout<<time(0)<<endl;
}
int main()
{
void* pF = PrintCurrentClock;
pF;
pF = PrintCurrentTimeStamp;
pF;
system("Pause");
return 0;
}
The output is empty, as if the *pF was somewhat "transparent".

Both C and C++ have function pointers that let you do what you are looking for:
void (*pf)(void);
pf = FunctionWithVeryVeryVeryLongNameThatPrintsTheCurrentClockStateUsingStdCoutOutputStream;
pf();
The void in parentheses is optional.
The reason you did not find anything on the topic is that for historic reasons both functions and procedures in C are called functions (the reason is that there were no void in the original language - procedures returned int by default, and the return value was ignored). C++ inherited this naming convention.

What you want are function pointers:
void (*pF)() = PrintCurrentClock;
pF();
(some people argue that writing &PrintCurrentClock is better style)
Notice that, as you can see, function pointers have a quite awkward syntax (especially if you start to have function pointers with "strange" arguments) and can prevent some compiler optimizations to work correctly, so they are usually used only when actually needed (e.g. for callbacks, although in C++ functors are often preferred).
Why does your code compile, although it doesn't work as expected? In
void* pF = PrintCurrentClock;
PrintCurrentClock is a void (*pF)(), which is implicitly converted to void *1; then, writing
pF;
you are evaluating the expression pF and discarding its return value - which is effectively a no-op (exactly as if you wrote 5; or any other expression that does not involve a function call).
Actually, this conversion shouldn't happen automatically, since the C++ standard do not provide an implicit conversion from function pointers to void *. Compiling this with g++ 4.6 correctly produces the errors:
matteo#teolapmint ~/cpp $ g++ -Wall -Wextra -ansi -pedantic testfuncptr.cpp
testfuncptr.cpp: In function ‘int main()’:
testfuncptr.cpp:19:20: error: invalid conversion from ‘void (*)()’ to ‘void*’ [-fpermissive]
testfuncptr.cpp:21:15: warning: statement has no effect [-Wunused-value]
testfuncptr.cpp:23:22: error: invalid conversion from ‘void (*)()’ to ‘void*’ [-fpermissive]
testfuncptr.cpp:25:23: warning: statement has no effect [-Wunused-value]
testfuncptr.cpp:27:39: error: ‘system’ was not declared in this scope
which tells you that those conversions are not admitted, that the pF; instructions are no-ops and that you forgot #include <cstdlib> (although system("pause"); is not portable anyway).

Your way of creating and using the function pointer is slightly off. Here's an example of how to do it:
void proc() {
cout << "Hello from proc" << endl;
}
...
void (*pproc)() = proc;
pproc();

Yes you can:
Though the type-system is a bit convoluted.
So it is usual to wrap a pointer to a function in a typedef.
typedef <returnType> (*<TypeName>)(<ParameterList>);
// In your case:
tpyedef void (*PtrToTimeFunc)();
// Now your pointer types look like normal variables:
PtrToTimeFunc pf = &PrintCurrentTimeStamp;
// Calling them is like normal:
pf(); // If it needed parameters then put them as normal.
Because the C++ compiler can not past function pointers to optimize the code; in C++ it is common to use functors. A functor is an object that behaves like a function, but because it is an object can also contain state (like a closure in other languages).
struct MyFunctor
{
// To make a functor just override the operator ()
// You can make it return any type and take any parameters (just like a function).
int operator()() const
{
return time(NULL);
}
// Add any state and constructors etc. you like here.
// Though note: because I declared the operator() as const you
// can not mutate the state via the function call (remove cost)
// if you want to do that.
};
// declaring a functor just like any-other object.
MyFunctor myFunctor;
// calling. Just like a function.
myFunctor();
OK. So why is this more useful than a pointer.
When used with the standard algorithms. You define the algorithm with the type of the functor thus the compiler generates the algorithm code it also has available all the code for the functor (unlike the function pointer which it can not optimize past). This allows the compiler to do a full set of optimizations in place.
std::generate(cont.begin(), cont.end(), myFunctor);
So in C++ 11 we have introduced lambdas. These are basically functions that can be defined in place. But it is easier to think of lambdas as compiler generated functors (as they can capture the current state as part of their definition).
std::generate(cont.begin(), cont.end(), [](){return time(NULL);});
// [] - defines the state that is being captured.
// Think of this like the constructor capturing objects.
// In this case take no state.
//
// () - parameter list
// In this case no parameters
//
// {} - The code.
A more interesting example:
std::vector<int> data; // fill vector
std::for_each(data.begin(), data.end(), [](int& value){value += 4;}); // Add 4 to each member.

Related

Explicitly passing *this in C++

While reading about *this, I saw:
When a nonstatic member function is called for an object, the compiler
passes the object's address to the function as a hidden argument.
Then I tried:
#include <iostream>
class MyClass
{
int myVar;
public:
MyClass(const int& val) : myVar{val} {}
// int getVar(MyClass* this) <-- Error: expected ',' or '...' before 'this'
int getVar()
{
return this->myVar;
}
};
int main()
{
MyClass obj(22);
// std::cout << obj.getVar(&obj); <-- Error: no matching function
// std::cout << MyClass::getVar(&obj); <-- Error: no matching function
std::cout << obj.getVar();
return 0;
}
Why am I not able to access the hidden argument? Is it called 'hidden' because of that?
Are only compilers allowed to do this? Can't we explicitly mention *this in the function signature?
The closest answer I've found before asking this is this. But I tried that way and still got the error. Could I get an explanation of those error messages? Because, if the compiler actually modifies those function signatures to contain *this then that should have worked, isn't it?
Are only compilers allowed to do this?
Precisely. That's why it's called hidden: It's something that the compiler does on your behalf, but which is hidden from the C++ code that uses it.
The compiler must pass the this pointer to the member function somehow, but it does not need to tell you how it does it. It could compile the code to the equivalent of MyClass::getVar(&obj), passing the this pointer in the same way that it would pass the argument for the C function free(foo). Or it might use a different mechanism that is totally incompatible with non-member argument passing. What it does under the hood is defined by the platform's Abstract Binary Interface standard (ABI), which is not part of the C++ language standard. What happens under Windows could be vastly different from what happens under Linux, and Linux on ARM could be different from Linux on X86, etc.
That said, you can take a look at what actually happens by telling your compiler to produce the assembly code. For gcc, the incantation would be
g++ -S -Os interestingCode.cpp
This will produce a .s file that contains how g++ actually translated your code.
obj.getVar(&obj)
This version cannot compile because the getVar() member function is not declared to take any parameters.
MyClass::getVar(&obj)
This version is using the syntax to access a static function but getVar() is not static, nor does it accept any parameters.
Note: The obj.getVar() call works because it is specifying which object instance to use (i.e., the obj. part) to execute the member function and is conceptually how the member function is passed the this pointer.
When you are doing obj.getVar() it is already explicitly specified the pointer *this=&obj and passed implicitly to getVar. It is not hidden. It is explicitly passed leftside of the function. You can use obj.getVar() or ptrObj->getVar() but in C++ is not allowed to use such construction getVar(thisptr). Hidden means the variable named this is nowhere declared, but you can use inside the function.

GCC allows arrays to be returned from function - bug or feature?

I was amazed to find out that GCC allows functions to return arrays when trailing return type is used instead of normal one. As you probably knows arrays can't be copied so this is quite limited but let me show you some cool example.
#include <iostream>
#include <typeinfo>
using namespace std;
auto func() -> int [5]
{
return {4, 56, 78, 4, 0};
}
int main()
{
cout << func()[2] << endl;
cout << typeid(func).name() << endl;
}
Is this a compiler bug or some new feature?
Interestingly 'typeid' returns 'FA5_ivE' which is demangled as 'int (()) [5]' and this means exactly what you think an function returning array of 5 int's.
EDIT: I tried bounding the returned array into rvalue reference but without any success (used most of the possible forms):
auto &&refArrayTemp{ func() };
Seems that this extensions is rather useless.
This was a bug in gcc (fixed as of 2017-07-03), caused by inconsistent treatment of trailing-return-types.
First note the difference in error message between two attempts to declare a function returning a function:
using Fv = void();
Fv f1(); // error: 'f1' declared as function returning a function
auto f2() -> Fv; // error: function return type cannot be function
The first error comes from decl.c, handling declarators, while the second is a lot deeper into the internals, from tree.c, attempting to build the function type preparatory to generating code.
Trailing-return-types are handled in decl.c 30 lines below the above error - too late to catch it with the above error code, and it is not handled separately.
With arrays, similarly using a trailing-return-type allows us to skip the checks in decl.c, the difference being that function-returning-array is actually valid in terms of gcc's internal representation.
Note that you can't do much with it; gcc doesn't allow you to assign, reference-bind, decay or pass the result of func() to another function:
auto a1 = func();
// error: invalid use of non-lvalue array
auto& a2 = func();
// error: invalid initialization of non-const reference of type 'int (&)[5]' from an rvalue of type 'int [5]'
auto&& a3 = func();
// error: lvalue required as unary '&' operand
Indeed, even your code is rejected at -Wpedantic:
warning: ISO C++ forbids subscripting non-lvalue array
Finally, by exploiting a similar bug (qualifiers are stripped from scalars before handling of trailing-return-types) we can create a function with type int const volatile():
int const volatile g1(); // warning: type qualifiers ignored on function return type
auto g2() -> int const volatile; // OK!!
Latest draft, [dcl.array]/p10:
Functions shall not have a return type of type array or function, although they may have a return type of
type pointer or reference to such things. There shall be no arrays of functions, although there can be arrays
of pointers to functions.
This could be a non-standard GCC extension. It doesn't compile in the trunk version of clang. However, this may also be a bug since it has inconsistent behavior with a non-trailing return type.

using typedef to wrap functions

One of my teachers use this type declaration:
typedef void (*SortFunction)(int a[], int n);
to create a type that can hold a pointer to a function
and that can be used to call that function later on in a program.
I also know that to pass a function as a parameter you have to
wrap the function name in parenthesis and wrap the function's
parameters in parenthesis after the function name as well like so
function someFunction( (anotherfunction)(type arg1, type arg2,...)){
...
}
What I want to know is why must you wrap a function in parenthesis like this? is this a built in function of most c++ compilers or is it simply a trick that we programmers use
in order to enable functions as arguments within our code? also, why does "SortFunction"
in the typedef statement need to be referenced, why can't the variable you use to utilize SortFunction just hold the function instead of pointing to it?
There's nothing special about function arguments. Whenever you declare a function pointer (as a local variable, global variable, class member variable, function parameter, typedef, etc.), it's always declared like so:
return_type (*var_name)(T1 param1, T2 param2, /* etc. */ );
// ^
// |
// This * is very important!
Where var_name is the name of the function pointer variable. The reason the parentheses are needed around *var_name is due to operator precedence: without the parentheses, the * (indicating that something's a pointer) would match with the function's return type, and instead you'd get something like a return type of int* (pointer to int) instead of plain int.
You can't pass a function as an argument because functions are not first-class objects in C and C++. The only way to pass a function is my passing a pointer to the function.
"I also know that to pass a function as a parameter you have to wrap the function name in parenthesis..." You "know " incorrectly.
In order to pass function pointer as a parameter you don't have to wrap the name in parentheses. For example, this will work perfectly fine
void foo(int i) {
}
void bar(void f(int)) {
f(5);
}
int main() {
bar();
}
In the above example function bar receives a pointer to function foo as a parameter and calls foo through that pointer, passing 5 as an argument. As you can see, function name f in the parameter declaration is not wrapped into parentheses.
In this case, once again, the type of parameter f is actually a pointer to a function, even though it is not explicitly declared as a pointer. When function type is used in function parameter declarations, it is automatically implicitly "replaced" with function pointer type by the compiler.
If you wanted to use the function pointer type explicitly, you have to declare bar as
void bar(void (*f)(int)) {
f(5);
}
In this case the parentheses in (*f) are necessary to assure that the * will get bound to f and not to void. Without parentheses the void *f(int) declaration would stand for "function returning void *" instead of the desired "pointer to function returning void".
It is a matter of syntax. Your first typedef defines a type which is a function receiving a vector of int and a int and returning nothing (void).
A variable of type SortFunction will be conceptually as any other variable, although it points to some function. The advantage is that you can change the function it points to and/or call the function dynamically.
What I want to know is why must you wrap a function in parenthesis like this?
Because there had to be some way to identify a function pointer to the compiler (or rather, the parser) and that way seemed as good as any. In C++11 land, you might use this instead: std::function<void(std::array<int>&)> instead.
is this a built in function of most c++ compilers or is it simply a trick that we programmers use in order to enable functions as arguments within our code?
Function pointers need a little bit of additional magic, and without compiler support they would be very, very inconvenient to use. I'm also reasonably certain that it is in the nature of programming that almost all programmer tricks are ultimately functions of the compiler!
also, why does "SortFunction" in the typedef statement need to be referenced, why can't the variable you use to utilize SortFunction just hold the function instead of pointing to it?
Hmm. Not totally sure what you mean here. Do you mean "why does this need to be a typedef at all... why couldn't I just write out the whole function pointer prototype in my function arguments"? Cos you can:
void foo(void(*funcptr)()) {}
If you meant "why do function pointers have to point at a function instead of having the code inline" then for that you need C++11 and lambdas:
#include <iostream>
#include <functional>
void foo(std::function<void(void)> bar) { bar(); }
int main(int argc, char* argv[])
{
foo([]() { std::cout << "hi!" << std::endl; });
}
(again, special syntax needed for lambdas, [](){}, just to tell the parser what is going on)

function pointers and return type conversions

Suppose I have a function that performs some side effect and then returns an answer:
int foo()
{
perform_some_side_effect();
return 42;
}
I want to bind foo to a function pointer, but I'm not interested in the answer, just the side effect:
void (*bar)() = foo;
However, this appears to be a type error:
error: invalid conversion from ‘int (*)()’ to ‘void (*)()’
What is the rationale behind that error? Why doesn't the type system allow me to ignore the answer?
On a side note, it works if I wrap the function pointer in a std::function:
std::function<void()> baz = foo;
How does std::function (apparently) manage to circumvent this restriction in the type system?
What is the rationale behind that error? Why doesn't the type system allow me to ignore the answer?
The reason is that the types are different, and the generated code at the place of call (through the function pointer) is different. Consider a calling convention where all arguments are written to the stack and space for the return value is also reserved in the stack. If the call goes through a void (*)() then no space will be reserved in the stack for the return value, but the function (unaware of how it is being called) will still write the 42 to the location where the caller should have reserved space.
How does std::function (apparently) manage to circumvent this restriction in the type system?
It does not. It creates a function object that wraps the call to the actual function. It will contain a member like:
void operator()() const {
foo();
}
Now when the compiler processes the call to foo it knows what it has to do to call a function that returns an int and it will do so according to the calling convention. Because the template does not return, it will just ignore the value --that was actually returned.
std::function need only be source compatible- that is, it can generate a new class which generates new caling code that ignores the result. The function pointer must be binary compatible and cannot do that job- void(*)() and int(*)() point to the exact same code.
You can think of std::function<> doing this for your particular case:
void __func_void()
{
foo();
}
It's actually a bit more complicated than that, but the point is that it generates template code together with type-erasure to not care about the specifics.
In addition to what others have been saying, the caller also need the return type to know what destructor it should invoke on the result (the return value may be a temporary).
Unfortunately it is not as easy as
auto (*bar)() = foo;
Although GCC and Clang accept this. I need to recheck the spec to see whether that's actually correct.
Update: The spec says
The auto type-specifier signifies that the type of a variable being declared shall be deduced from its initializer or that a function declarator shall include a trailing-return-type.
This can be misleading when read fast, but this is implemented by GCC and clang to only apply to the toplevel declarator. In our case, this is a pointer declarator. The declarator nested in it is a function declarator. So just substitute auto for void and then the compiler will deduce the type for you.
By the way, you can always make this work manually, but it takes some trickery to make it work
template<typename FunctionType>
struct Params;
template<typename ...Params>
struct Params<void(Params...)> {
template<typename T>
using Identity = T;
template<typename R>
static Identity<R(Params...)> *get(R f(Params...)) {
return f;
}
};
// now it's easy
auto bar = Params<void()>::get(foo);

Template function causes a compiler error when used with local lambda

My previous question concluded that a distasteful "double cast" might be necessary to use the POSIX makecontext with a C++ lambda function (i.e. function object). Moving on, I'm now faced with a compilation error relating to the following minimal code:
#include <iostream>
#include <ucontext.h>
using namespace std;
template <typename T> void foo() {
ucontext_t c;
auto f = [=](int i){ cout << i << endl; };
makecontext(&c, (void (*) (void)) (void (*)(int)) f, 1, 12345);
}
int main(int argc, char *argv[]) {
foo<int>();
return 0;
}
The error is:
error: invalid cast from type ‘foo() [with T = int]::<lambda(int)>’ to type ‘void (*)(int)’
However, if I remove the unused (in this example) template argument from the foo function, so it becomes void foo();, and change the call to foo() the error disappears. Could someone tell me why? I'm using G++ 4.6.
Edit:
From the comments below, it seems the [=] in the code above causes the lambda to be a "capturing" lambda, regardless of the fact that it doesn't actually capture anything. The [=] is not necessary in my code, alas replacing with [] in GCC 4.6 does not remove the error. I am installing GCC 4.6.1 now...
If you use [=] to induce your lambda, you will not get a function pointer (or an object that is convertible to one). You will get a function object. And no amount of casting is going to allow you to pass that to makecontext. Not in any way that actually works.
According to N3291, the most recent working draft of C++0x:
The closure type for a lambda-expression with no lambda-capture has a public non-virtual non-explicit const conversion function to pointer to function having the same parameter and return types as the closure type’s function call operator. The value returned by this conversion function shall be the address of a function that, when invoked, has the same effect as invoking the closure type’s function call operator.
This is the only place where the specification allows conversion to a function pointer. Therefore, if recent versions of GCC do allow conversion to function pointers for [=], that not in accord with the specification.
Only captureless lambdas are convertible to function pointers; while f technically does not capture anything, it does have a default capture mode of capturing by value (for no apparent reason).
Change [=] to [] in the declaration of f and it should work as expected.
EDIT: The fact that this compiles with more recent versions of GCC (as noted by Kerrek) gives a strong indication that this is merely a compiler bug in the version you're using.