I want to declare type definition for a member function signature. Global function typedefs look like this:
typedef int (function_signature)(int, int);
typedef int (*function_pointer) (int, int);
But I'm not able to the same thing for a member function:
typedef int (foo::memberf_signature)(int, int); // memberf_pointer is not a member of foo
typedef int (foo::*memberf_pointer)(int, int);
It sounds logically to me, because foo:: is the syntax to access a member in the class foo.
How can I typedef just the signature?
For questions regarding the awkward function pointer syntax, I personally use a cheat-sheet: The Function Pointers Tutorial (downloadable here, thanks to Vector for pointing it out).
The signature of a member function, however, is a bit different from the signature of a regular function, as you experienced.
As you probably know, a member function has a hidden parameter, this, whose type need be specified.
// C++11 and above.
using Member = int (Foo::*)(int, int);
// C++03 and below.
typedef int (Foo::*Member)(int, int);
does let you specify that the first element passed to the function will be a Foo* (and thus your method really takes 3 arguments, when you think of it, not just 2.
However there is another reason too, for forcing you to specify the type.
A function pointer might refer to a virtual function, in which case things can get quite complicated. Therefore, the very size of the in-memory representation changes depending on the type of function. Indeed, on Visual Studio, a function pointer's size might vary between 1 and 4 times the size of a regular pointer. This depends on whether the function is virtual, notably.
Therefore, the class the function refers to is part of the signature, and there is no work-around.
You can factor out the target class in modern C++ (post 11) by utilizing the 'typedefing' qualities of template aliases. What you need would look like like:
template<typename T>
using memberf_pointer = int (T::*)(int, int);
Yet at the point of declaration, a pointer to member function utilizing this syntax would need to specify the target class:
// D is a member function taking (int, int) and returning int
memberf_pointer<foo> mp = &foo::D;
The reason it doesn't work with your current syntax is that operator precedence dictates that you're referring to a function named foo::memberf_signature, not any sort of type.
I don't know for sure if you can do this or not, but I couldn't come up with any combination of parenthese that induced the code to compile with g++ 4.2.
It works for me:
#include <iostream>
class foo
{
public:
int g (int x, int y) { return x + y ; }
} ;
typedef int (foo::*memberf_pointer)(int, int);
int main()
{
foo f ;
memberf_pointer mp = &foo::g ;
std::cout << (f.*mp) (5, 8) << std::endl ;
}
Well basically it can't work (at least I know no way using g++);
Using borland c++ compiler there would be the __closure keyword.
The reason why it does not compile is, that sizeof the functionpointer (on a x86 machine) occupies always <<32bits>>; but if you want to point to a class (interface) signature, the sizeof has to be 64bit: 32 bit for the this pointer (as the class interface is in the memory only once) and 32 bit for the actual function
But the __closure keyword is a bcb language 'hack' not standardized...
Related
Given a function in C++ with arguments that are only types and have no identifiers,
void foo1(int, int, int){cout << "called foo1";}
I can call it as such:
int main()
{
foo1(10, 10, 10);
}
Why is this a valid construct in C++? Is this just an idiosyncrasy of C++, or does this kind of declaration actually have some purpose? Can we actually access the arguments that have been passed in somehow?
(This kind of method declaration will not work in Java.)
Consider a case where you are required to provide a function that meets the following prototype
void dostuff(int x, int y, int z);
And say you are operating in a 2D space and do not use z inside your implementation. You can
void dostuff(int x, int y, int z)
{
// use x and y
}
and just ignore z, but the compiler will likely spot that you have defined but not used z and warn you that you could be making a mistake. Instead you can
void dostuff(int x, int y, int )
{
// use x and y
}
and leave out the definition of z. The compiler will accept and silently discard the third parameter because it knows you don't want it.
You do not want to simply turn off the warning because of errors like this
void dostuff(int x, int y, int z)
{
for (int z = 0; z < MAX; z++)
{
// use x and y and z, the local z.
}
}
Where a poorly-named loop index shadows the parameter z. The caller's input is now ignored and this could have bad consequences. This error is often hard to spot with the mark 1 eyeball, especially if the local z is buried somewhere deep in a complex function.
Anytime the compiler can pick off a possible bug in your code, take advantage. It means less work for you.
A declaration like
void foo1(int, int, int){cout << "called foo1";}
clearly shows in the declaration, that you want to fulfill a requirement with your function - e.g. override a specific function in the base class or interface, which e.g. could be declared there as
virtual void foo1(int something, int another, int andAnother) = 0;
BUT you don't intend to use the parameters which are handed over to you.
Another example would be if you want to hand over the function to e.g. another function which expects a function pointer to a void function with three int parameters.
void giveMeFoo( void (*fn)(int, int, int) ) { ... }
Additionally, higher warning levels issue a warning, if parameters are declared, which are not evaluated in the function body. You can avoid that by leaving the parameter names away.
The parameters without names are then indeed not accessible in the function body anymore - on purpose. user4581301 has nicely described, why.
Declaring a standalone function without parameter names as in your example is allowed because of the usages described above, but it obviously makes no sense in most cases. An example where it does make sense is in the comment section. Another example of a standalone function without parameter names could be, if your'e writing a library and want to either maintain backward compatibility (your library function does not need the parameter anymore, but you don't want to break the public header declaration) or you want to reserve a parameter for future use.
Yes. It is legal in C++.
C++11 n3337 standard 8.4.1(p6) Function definitions:
Note: Unused parameters need not be named. For example,
void print(int a, int) {
std::printf("a = %d\n", a);
}
C++14 standard:
[ 8.3.5.11] An identifier can optionally be provided as a parameter name; if present in a function definition , it names a parameter
(sometimes called “formal argument”). [Note: In particular, parameter
names are also optional in function definitions and names used for a
parameter in different declarations and the definition of a function
need not be the same.]
It's legal, and if you're wondering why:
Typically, unnamed arguments arise from the simplification of code or
from planning ahead for extensions. In both cases, leaving the
argument in place, although unused, ensures that callers are not
affected by the change.
Excerpt From: Bjarne Stroustrup. “The C++ Programming Language, Fourth Edition.”
The idea is that you might want to change the function
definition to use the placeholder later, without changing all the
code where the function is called.
Arguments in a function declaration can be declared without
identifiers. When these are used with default arguments, it can look
a bit funny. You can end up with :
void f(int x, int = 0, float = 1.1);
In C++ you don’t need identifiers in the function definition, either:
void f(int x, int, float flt) { /* ... */ }
In the function body, x and flt can be referenced, but not the
middle argument, because it has no name. Function calls must still
provide a value for the placeholder, though: f(1) or f(1,2,3.0). This
syntax allows you to put the argument in as a placeholder without
using it.
Unnamed parameters can also be used for the tag dispatch idiom:
template<typename T>
void foo(T&& t){
foo(std::forward<T>(t), std::is_same_v<std::remove_ref<std::remove_const<T>>>, std::string>); // do something special with strings
template<typename T>
void foo(T&& t, std::false_type); // note no parameter name
template<typename T>
void foo(T&& t, std::true_type);
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)
I'm used to seeing syntax like this for function pointers
int (*pointer_name) (float, char *);
void call_function (void (*)(int), int);
In some C++03 functional libraries I see types used this way:
abc::function<void(*)(int,float)> f;
In C++11's std::function I see the type given this way
std::function<void(int,float)> f;
There is a missing (*). Why?
The C++03 function<T> has T being an identical type to the corresponding function pointer. It's easy to imagine the implementation.
std::function in C++11 is supported by core language enhancements. Have template argument types been extended to accomodate callability?
std::function (and its inspiration, boost::function) does not only store function pointers. It can also store function objects. In that sense, passing a function signature as a template parameter is similar to how a smart pointer usually take the type of the pointee as a template parameter, not a pointer type!
Contrast:
int* p; // indirection to an object of type int
std::unique_ptr<int> q; // indirection to an object of type int
with
typedef void signature_type(); // a function type
// indirection to something callable with signature_type as a signature
// i.e. f() has type void
// only work for freestanding functions however
signature_type* f;
// indirection to something callable with signature_type as a signature
// i.e. g() has type void
// not restricted to function pointers!
std::function<signature_type> g;
This is a useful convention.
There is nothing magic here, the type
void(int,float)
is the type of a function without the names. It matches a function like void g(int x, float y).
With templates you don't have to use function pointers, you can use function types as well.
As with other elements, functions have a type, and you can use either the type or the pointer to the type in different contexts. The missing (*) you are expecting is just the pointer-to syntax.
int (*pointer_name) (float, char *);
typedef int my_function_type(float,char*);
my_function_type * pointer_name2;
The types of pointer_name and pointer_name2 are the same: pointer to a function that returns int and takes two arguments of types float and char*. Note that this is exactly equivalent to other types like int, with the difference that you cannot declare a variable to be of type function, only pointer to function.
The interface of std::function (or boost::function) just takes the signature of the function. The type argument is not a pointer to function but rather the type of a function (like my_function_type in the code above)
Function types aren't new in C++11 (see 8.3.5 in C++98). IIRC, the improvement over what TR1 and boost provide for function are quite minor.
Reading the C++ Standard, i see that there are "function" types and "pointer to function" types:
typedef int func(int); // function
typedef int (*pfunc)(int); // pointer to function
typedef func* pfunc; // same as above
I have never seen the function types used outside of examples (or maybe i didn't recognize their usage?). Some examples:
func increase, decrease; // declares two functions
int increase(int), decrease(int); // same as above
int increase(int x) {return x + 1;} // cannot use the typedef when defining functions
int decrease(int x) {return x - 1;} // cannot use the typedef when defining functions
struct mystruct
{
func add, subtract, multiply; // declares three member functions
int member;
};
int mystruct::add(int x) {return x + member;} // cannot use the typedef
int mystruct::subtract(int x) {return x - member;}
int main()
{
func k; // the syntax is correct but the variable k is useless!
mystruct myobject;
myobject.member = 4;
cout << increase(5) << ' ' << decrease(5) << '\n'; // outputs 6 and 4
cout << myobject.add(5) << ' ' << myobject.subtract(5) << '\n'; // 9 and 1
}
Seeing that the function types support syntax that doesn't appear in C (declaring member functions), i guess they are not just a part of C baggage that C++ has to support for backward compatibility.
So is there any use for function types, other than demonstrating some funky syntax?
On the one hand, you seem to be talking about function types in general. On the other hand, it appears that your question is really about the usability of typedef names for function types.
The function types themselves is a fundamental concept built into both C and C++ languages. They are used all the time. You just can't live without them. Every time you declare a function you declare an entity of function type. Every time you use a pointer to a function, you use a pointer to function type. Etc.
As for the possibility of making typedef names for function types... I don't see much use for it. It is, I think, a part of C baggage, that was extended a bit for C++ just because it was easy to do.
As you correctly noted typedef names for function types can be used to declare member functions (and in C++ you can also include const specifier into typedef, as in typedef int MemberType() const;), but, for example, you can't use this feature with function types passed as template parameters.
An example of why this is useful is boost, where you see this a lot. For example in the signals2 library:
boost::signals2::signal<void (int, int)> MySignal;
where the above declares a signal that will accept any function that takes two ints and has a void return type.
boost:function uses that syntax, called "preferred" syntax.
Seems that kind of syntax is not widely used? Comparing to function pointer.
You see it in the new function objects in Boost/TR1/C++0x.
std::function<void()> accepts any object with an operator() that returns void and takes no arguments.
Is it posible to use the type of a prefiously declared function as a function pointer without using a typedef?
function declaration:
int myfunc(float);
use the function declaration by some syntax as function pointer
myfunc* ptrWithSameTypeAsMyFunc = 0;
Not as per the 2003 standard. Yes, with the upcoming C++0x standard and MSVC 2010 and g++ 4.5:
decltype(myfunc)* ptrWithSameTypeAsMyFunc = 0;
Yes, it is possible to declare a function pointer without a typedef, but no it is not possible to use the name of a function to do that.
The typedef is usually used because the syntax for declaring a function pointer is a bit baroque. However, the typedef is not required. You can write:
int (*ptr)(float);
to declare ptr as a function pointer to a function taking float and returning int -- no typedef is involved. But again, there is no syntax that will allow you to use the name myfunc to do this.
Is it posible to use the type of a prefiously declared function as a function pointer without using a typedef?
I'm going to cheat a bit
template<typename T>
void f(T *f) {
T* ptrWithSameTypeAsMyFunc = 0;
}
f(&myfunc);
Of course, this is not completely without pitfalls: It uses the function, so it must be defined, whereas such things as decltype do not use the function and do not require the function to be defined.
No, not at the present time. C++0x will change the meaning of auto, and add a new keyword decltype that lets you do things like this. If you're using gcc/g++, you might also look into using its typeof operator, which is quite similar (has a subtle difference when dealing with references).
No, not without C++0x decltype:
int myfunc(float)
{
return 0;
}
int main ()
{
decltype (myfunc) * ptr = myfunc;
}
gcc has typeof as an extension for C (don't know about C++) ( http://gcc.gnu.org/onlinedocs/gcc/Typeof.html ).
int myfunc(float);
int main(void) {
typeof(myfunc) *ptrWithSameTypeAsMyFunc;
ptrWithSameTypeAsMyFunc = NULL;
return 0;
}
int (*ptrWithSameTypeAsMyFunc)(float) = 0;
See here for more info on the basics.