I'm reading a lot about "typedef functions", but I getting casting errors when I try to call this one. What's the correct syntax to call this function?
typedef ::com::Type* Func(const char* c, int i);
that statement makes Func a type. Then you'll have to say Func *f = anotherFunc given another func is defined as : ::com::Type* anotherFunc(const char *c, int i){ /*body*/ }
Then you can call f("hello", 0) and it should work.
There's no function in your code. There's only a type name Func that stands for function type. There's nothing to call there.
The name Func, as defined in your question, can be used in several different ways.
For example, you can use it to declare a function
Func foo;
The above is equivalent to declaring
::com::Type* foo(const char*, int);
This will also work for member function declarations. (However, you can't use it to define a function).
For another example, you can use it when declaring a pointer to a function, by adding an explicit *
Func *ptr = &some_other_function;
The above is equivalent to declaring
::com::Type* (*ptr)(const char*, int) = &some_other_function;
For yet another example, you can use it as a parameter type in another function
void bar(Func foo)
in which case the function type will automatically decay to function pointer type, meaning that the above declaration of bar is equivalent to
void bar(Func *foo)
and equivalent to
void bar(::com::Type* (*foo)(const char*, int));
And so on.
In other words, show us what your are trying to do with it. As is your question is too broad to be answered specifically.
typedef function syntax:
#include <iostream>
using namespace std;
int add(int a, int b) {return a+b;}
typedef int(*F)(int a, int b);
int main() {
F f = add;
cout << f(1,2) << endl;
return 0;
}
The break down of typedef int(*F)(int a, int b);
The type name is F in brackets
Return type is the int at the beginning.
The parameters are (int, int)
Usage F f = &add;:
F is our type.
f is the variable name.
add is the function with the correct signature.
A valid syntax in your case would be: typedef ::com::Type (*Func)(const char* c, int i);
Related
I have come across this code snippet and have no idea what it means:
#include <iostream>
int main(){
using test = int(int a, int b);
return 0;
}
I can guess test can be used instead of int(int a, int b), but what does int(int a, int b) even mean? is it a function? How can it be used?
int(int a, int b) is a function declaration that has two parameters of the type int and the return type also int.
You can use this alias declaration for example as a member function declarations of a class or using it in a parameter declaration.
It's an alias for a function signature.
A more complete usage is to declare a pointer or reference to a function
int foo(int, int);
int main()
{
using test = int(int a, int b); // identifiers a and b are optional
test *fp = &foo;
test *fp2 = foo; // since the name of function is implicitly converted to a pointer
test &fr = foo;
test foo; // another declaration of foo, local to the function
fp(1,2); // will call foo(1,2)
fp2(3,4); // will call foo(3,4)
fr(5,6); // will call foo(5,6)
foo(7,8);
}
Just to give another use option of this line, with lambda expressions:
int main() {
using test = int(int, int);
test le = [](int a, int b) -> int {
return a + b;
}
return 0;
}
One point that you have to keep in mind about this use of test, there are probably more efficient ways to declare a function signature, like auto in lambda expressions case, template in case of passing function as argument to another function, etc.
This way came all the way from pure C programming, with the using twist. I won't recommend of choosing this way, but for general understanding it is always good to know more than the correct ways.
I'm having trouble understanding function signatures and pointers.
struct myStruct
{
static void staticFunc(){};
void nonstaticFunc(){};
};
int main()
{
void (*p)(); // Pointer to function with signature void();
p = &myStruct::staticFunc; // Works fine
p = &myStruct::nonstaticFunc; // Type mismatch
}
My compiler says that the type of myStruct::nonstaticFunc() is void (myStruct::*)(), but isn't that the type of a pointer pointing to it?
I'm asking because when you create an std::function object you pass the function signature of the function you want it to point to, like:
std::function<void()> funcPtr; // Pointer to function with signature void()
not
std::function<void(*)()> funcPtr;
If I had to guess based on the pattern of void() I would say:
void myStruct::();
or
void (myStruct::)();
But this isn't right. I don't see why I should add an asterisk just because it's nonstatic as opposed to static. In other words, pointer void(* )() points to function with signature void(), and pointer void(myStruct::*)() points to function with signature what?
To me there seems to be a basic misunderstanding of what a member pointer is. For example if you have:
struct P2d {
double x, y;
};
the member pointer double P2d::*mp = &P2d::x; cannot point to the x coordinate of a specific P2d instance, it is instead a "pointer" to the name x: to get the double you will need to provide the P2d instance you're looking for... for example:
P2d p{10, 20};
printf("%.18g\n", p.*mp); // prints 10
The same applies to member functions... for example:
struct P2d {
double x, y;
double len() const {
return sqrt(x*x + y*y);
}
};
double (P2d::*f)() const = &P2d::len;
where f is not a pointer to a member function of a specific instance and it needs a this to be called with
printf("%.18g\n", (p.*f)());
f in other words is simply a "selector" of which of the const member functions of class P2d accepting no parameters and returning a double you are interested in. In this specific case (since there is only one member function compatible) such a selector could be stored using zero bits (the only possible value you can set that pointer to is &P2d::len).
Please don't feel ashamed for not understanding member pointers at first. They're indeed sort of "strange" and not many C++ programmers understand them.
To be honest they're also not really that useful: what is needed most often is instead a pointer to a method of a specific instance.
C++11 provides that with std::function wrapper and lambdas:
std::function<double()> g = [&](){ return p.len(); };
printf("%.18g\n", g()); // calls .len() on instance p
std::function<void()> funcPtr = std::bind(&myStruct::nonstaticFunc, obj);
Is how you store a member function in std::function. The member function must be called on a valid object.
If you want to delay the passing of an object until later, you can accomplish it like this:
#include <functional>
#include <iostream>
struct A {
void foo() { std::cout << "A::foo\n"; }
};
int main() {
using namespace std::placeholders;
std::function<void(A&)> f = std::bind(&A::foo, _1);
A a;
f(a);
return 0;
}
std::bind will take care of the details for you. std::function still must have the signature of a regular function as it's type parameter. But it can mask a member, if the object is made to appear as a parameter to the function.
Addenum:
For assigning into std::function, you don't even need std::bind for late binding of the object, so long as the prototype is correct:
std::function<void(A&)> f = &A::foo;
p = &myStruct::staticFunc; // Works fine
p = &myStruct::nonstaticFunc; // Type mismatch
Reason : A function-to-pointer conversion never applies to non-static member functions because an lvalue that refers to a non-static member function
cannot be obtained.
pointer void(* )() points to function with signature void(), and pointer void(myStruct::*)() points to function with signature what?
myStruct:: is to make sure that the non-static member function of struct myStruct is called (not of other structs, as shown below) :
struct myStruct
{
static void staticFunc(){};
void nonstaticFunc(){};
};
struct myStruct2
{
static void staticFunc(){};
void nonstaticFunc(){};
};
int main()
{
void (*p)(); // Pointer to function with signature void();
void (myStruct::*f)();
p = &myStruct::staticFunc; // Works fine
p = &myStruct2::staticFunc; // Works fine
f = &myStruct::nonstaticFunc; // Works fine
//f = &myStruct2::nonstaticFunc; // Error. Cannot convert 'void (myStruct2::*)()' to 'void (myStruct::*)()' in assignment
return 0;
}
When you use a pointer, std::function or std::bind to refer to a non-static member function (namely, "method" of class Foo), the first param must be a concrete object of class Foo, because non-static method must be called by a concrete object, not by Class.
More details: std::function and
std::bind.
The answer is in the doc.
Pointer to member declarator: the declaration S C::* D; declares D as
a pointer to non-static member of C of type determined by
decl-specifier-seq S.
struct C
{
void f(int n) { std::cout << n << '\n'; }
};
int main()
{
void (C::* p)(int) = &C::f; // pointer to member function f of class C
C c;
(c.*p)(1); // prints 1
C* cp = &c;
(cp->*p)(2); // prints 2
}
There are no function with signature void (). There are void (*)() for a function or void (foo::*)() for a method of foo. The asterisk is mandatory because it's a pointer to x. std::function has nothing to do with that.
Note: Your confusion is that void() is that same signature that void (*)(). Or even int() <=> int (*)(). Maybe you think that you can write int (foo::*) to have a method pointer. But this is a data member pointer because the parenthesis are optional, int (foo::*) <=> int foo::*.
To avoid such obscure syntax you need to write your pointer to function/member with the return type, the asterisk and his parameters.
I am trying to pass a member function as argument using pointer-to-member-function. I have already seen some links like this here but I could not solve the problem.
The class Foo has two member functions. I need to pass the addition function as an argument to the NewOper function.
This is my code. I can correctly use pointer to call the addition function but it gives me an error when I try to pass it as an argument to NewOper function. I appreciate it if you tell me how I can fix it. (The last two lines cause error)
#include <iostream>
using namespace std;
class Foo{
public:
int addition(int a, int b)
{
return (a + b);
}
int NewOper(int x, int y, int(*fnc2call)(int, int))
{
int r;
r = (*fnc2call)(x, y);
return (r);
}
};
int main()
{
int m,n, k, l;
int (Foo::*fptr) (int, int) = &Foo::addition;
Foo obj;
m=(obj.*fptr)(1,2);
Foo* p = &obj;
n=(p->*fptr)(3,4);
cout << m << endl;
cout << n << endl;
//**********************
int (Foo::*fptr) (int, int, int(*fnc2call)) = &Foo::NewOper;
k = (obj.*fptr)(1, 2, addition);
}
You already have answer in your own code:
int (Foo::*fptr) (int, int) = &Foo::addition - here you correctly declared fptr as pointer to function, which is (non static) member of class Foo
But you forgot to do the same in you NewOper function definition:
int NewOper(int x, int y, int(*fnc2call)(int, int)) - this function wants address of free function as 3rd argument. Redefine it in the same way you declared fptr. But then you'll need to pass also pointer to an object of class Foo to this function
Alternatively, you can make your function addition function static as Jarod42 suggested (actually, the way it is written now, there is no reason for it to be member of class Foo unless you have further plan on it). Then you'll need to remove Foo:: from fptr definition
After getting an answer to this question I discovered there are two valid ways to typedef a function pointer.
typedef void (Function) ();
typedef void (*PFunction) ();
void foo () {}
Function * p = foo;
PFunction q = foo;
I now prefer Function * p to PFunction q but apparently this doesn't work for pointer-to-member functions. Consider this contrived example.
#include <iostream>
struct Base {
typedef void (Base :: *Callback) ();
//^^^ remove this '*' and put it below (i.e. *cb)
Callback cb;
void go () {
(this->*cb) ();
}
virtual void x () = 0;
Base () {
cb = &Base::x;
}
};
struct D1 : public Base {
void x () {
std :: cout << "D1\n";
}
};
struct D2 : public Base {
void x () {
std :: cout << "D2\n";
}
};
int main () {
D1 d1;
D2 d2;
d1 .go ();
d2 .go ();
}
But if I change it to the new preferred style: typedef void (Base :: Callback) () and Callback * cb, I get a compiler error at the point of typedef
extra qualification 'Base::' on member 'Callback'
Demo for error.
Why is this not allowed? Is it simply an oversight or would it cause problems?
For non-member functions, a type such as typedef void(Function)() has several uses, but for member functions the only application is to declare a variable which holds a function pointer. Hence, other than a stylistic preference, there's no strict need to allow this syntax and it has been omitted from the standard.
Background
The :: is a scope resolution operator, and the syntax X::Y is reserved for static member access if X is a class type. So X::*Z was another syntax invented to define pointer-to-member.
Forget member-function for a while, just think about member-data, and see this code:
struct X
{
int a;
};
int X::*pa = &X::a; //pointer-to-member
X x = {100}; //a = 100
cout << (x.*pa) << endl;
It defines a pointer-to-member-data, and the cout uses it to print the value of a of object x, and it prints:
100
Demo : http://www.ideone.com/De2H1
Now think, if X::pa (as opposed to X::*pa) were allowed to do that, then you've written the above as:
int X::pa = X::a; //not &X::a
Seeing this syntax, how would you tell if X::a is a static member or non-static member? That is one reason why the Standard came up with pointer-to-member syntax, and uniformly applies it to non-static member-data as well as non-static member-function.
In fact, you cannot write X::a, you've to write &X::a. The syntax X::a would result in compilation error (see this).
Now extend this argument of member-data to member-function. Suppose you've a typedef defined as:
typedef void fun();
then what do you think the following code does?
struct X
{
fun a;
};
Well, it defines member a of type fun (which is function taking no argument, and returning void), and is equivalent to this:
struct X
{
void a();
};
Surprised? Read on.
struct X
{
fun a; //equivalent to this: void a();
};
void X::a() //yes, you can do this!
{
cout << "haha" << endl;
}
We can use exactly the same syntax to refer to a which is now a member-function:
X x;
x.a(); //normal function call
void (X::*pa)() = &X::a; //pointer-to-member
(x.*pa)(); //using pointer-to-member
The similarity is the synatax on the right hand side : &X::a. Whether a refers to a member-function or member-data, the syntax is same.
Demo : http://www.ideone.com/Y80Mf
Conclusion:
As we know that we cannot write X::a on the RHS, no matter if a is a member-data or member-function. The only syntax which is allowed is &X::f which makes it necessary that the target type (on LHS) must be pointer as well, which in turn makes the syntax void (X::*pa)() absolutely necessary and fundamental, as it fits in with other syntax in the language.
To be precise the two typedef's in the case of the non-member pointers are not the same:
typedef void function();
typedef void (*fptr)();
The first defines function as a function taking no arguments and returning void, while the second defines ftpr as a pointer to function taking no arguments and returning void. The confusion probably arises as the function type will be implicitly converted to a pointer type in many contexts. But not all:
function f; // declares void f();
struct test {
function f; // declares void test::f()
};
void g( function f ); // declares g( void (*f)() ): function decays to pointer to function in declaration
g( f ); // calls g( &f ): function decays to pointer to function
void f() {} // definition of f
// function h = f; // error: cannot assign functions
function *h = f; // f decays to &f
Let's skip the "function" part for a second. In C++, we have the int, the int* and the int Foo::* types. That's a regular integer, pointer to integer, and a pointer to an integer member. There is no fourth type "integer member".
Exactly the same applies to functions: there's just no type "member function", even though there are function types, function pointer types, and member function pointer types.
I'm told to create template of function , that will take 4 arguments :
pointer
reference
pointer to array
pointer to function
How to perform this task ? I was trying :
#include <iostream>
using namespace std;
int nothing(int a)
{
return a;
}
template<typename T> T func(int *L, int &M, char *K, int (*P)(int))
{
cout << L << "," << M << "," << K[0] << "," << P() << endl;
return 0;
}
int main()
{
int x = 3;
int *z = &x;
int &y = x;
char c[3];
int (*pf)(int) = nothing;
cout << "some result of func" << func(z, y, c, pf) << endl;
system("pause");
return 0;
}
This gives me "no matching function , I guess for 'pf'. Also now I have no control over what to pass within pf or am I wrong ?
You're almost there. However, in C++, a reference is denoted with & (not $), a pointer to an array is a pointer to its first element, and a function pointer needs additional parentheses: T (*pf)().
Note that it is called a function template (as opposed to class templates).
Edit: (You shouldn't edit your question so that answers given so far suddenly become nonsensical.)
pf(x) calls the function stored in pf. pf already is a function pointer, so pass it as it is.
(Also, in your declaration P is a function taking an X, while pf takes an int. I suppose this is an editing error?)
Note that, with function pointers, there are 1..N types involved, one result type, and 0..N argument types. "Create a function template that will take a pointer to a function" can mean any of that. Or it means
template< typename F >
void f(F func);
which can be called with any function pointer.
To help you little bit more, try to remember how the "main" function taking arguments looks like, this will help you to see how you can make a pointer to an array.
You now have some problems left...
TYPE (*P)(x) says you expect a pointer to function that takes an argument of type x - change it to an existing type.
In the expression func(z, y, c, pf(x)) you try to call the function pointer pf instead of just passing it.
Then you are calling func with parameters based on different types for the first 3 parameters, int and char, but func expects them to be based on the same type.
Try writing down with what types func will be called with and try matching that to a signature for func with TYPE being substituted to say int.
E.g. if you have the following:
template<typename T> void f(T* a, T* b);
and try to call it like this:
int* a = 0;
int* b = 0;
f(a, b);
the compiler instantiates and calls a function
void f<int>(int*, int*);
But if you do the following:
int* a = 0;
char* b = 0;
f(a, b);
what should be called?
void f<int> (int*, int* ); // doesn't match, 2nd argument is char*
void f<char>(char*, char*); // doesn't match, 1st argument is int*