void Frame::ExtractORB(int flag, const cv::Mat &im)
{
if(flag==0)
(*mpORBextractorLeft)(im,cv::Mat(),mvKeys,mDescriptors);
else
(*mpORBextractorRight)(im,cv::Mat(),mvKeysRight,mDescriptorsRight);
}
How to use like this format?
(*name)(param1, param2, param3, param4)
this code is belong to orb_slam ....
https://github.com/raulmur/ORB_SLAM2
A declaration of a pointer to a non-member function has the following structure:
return-type (* name)(argument-list)
So in order to declare a pointer functo a function taking a const char* and an intas an argument and returning bool you say
bool (*func)(const char*, int);
Note, that you need the parenthesis around the *func, because otherwise the compiler would interpret it as a declaration of function
bool* func(const char*, int);
returning bool*.
Assume now, that you have a function
bool foo(const char* x, int y) { /* ... */ }
of corresponding type, then you can make your pointer point to this function by
func = &foo;
In order to invoke the function pointed to by func, you dereference the pointer and invoke it with the arguments like this
bool result = (*func)("abc", 3);
This is what you are doing in the example you provided. Calling the function pointed to by mpORBextractorLeft (resp. mpORBextractorRight) with the given arguments.
Some further notes:
Dereferencing of the function pointer may be omitted, so
bool result = func("abc", 3);
should work as well.
When declaring the pointer, it can be initialized immediately:
bool (*func)(const char*, int) = &foo;
A typedef can be used to simplify code if you need to write the type of the pointer multiple times:
typedef bool (*fun_ptr)(const char*, int);
fun_ptr func1 = &foo;
fun_ptr func2 = &bar;
Related
First off I would like to mention that this works with MSVC but not with clang. I am using Clang with c++11.
I have a function pointer:
typedef void (*Log) (const char* title, const char* msg, const char* file, int line);
I have this struct:
struct FunctionList
{
protected:
static const int kNbrMax = 32;
FunctionList();
bool Add(const void* f);
bool Remove(const void* f);
const void* m_functions[kNbrMax];
};
And this class:
template<typename T>
struct MessageFunctionList
: public FunctionList
{
public:
MessageFunctionList(T defaultFunction)
{
Add(defaultFunction);
}
void Call(const char* title,const char* cause,const char* file,int line)
{
for (unsigned long i = 0;i < m_nbrUsed;++i)
{
reinterpret_cast<T>(m_functions[i])(title,cause,file,line);
}
}
}
I am creating it like so:
static void DefaultLogMessageFunction(const char* title,const char* msg,const char* file,int line)
{
}
MessageFunctionList<Log> functionList(DefaultLogMessageFunction)
But I get the compile time error:
reinterpret_cast from 'const void ' to 'void ()(const char *, const
char *, const char *, int)' casts away qualifiers for line:
reinterpret_cast(m_functions[i])(title,cause,file,line);
So as far as I understand I am trying to cast my const list of functions to a non const value. That is not allowed which makes sense. So I tried the following:
const void* funcPtr = m_functions[i];
const T call = reinterpret_cast<const T>(funcPtr);
call(title, cause, file, line);
But that does not work either.
This works:
void* funcPtr = const_cast<void*>(m_functions[i]);
T call = reinterpret_cast<T>(funcPtr);
call(title,cause,file,line);
But I would like to avoid using a const cast. What am I doing wrong? How can I call this const function? Or is it simply not allowed because it does not know if the function being called is a const function or not? Or perhaps it is because my static function is not a member of a class so it can not be declared const?
You are storing the function pointers as const void*:
const void* m_functions[kNbrMax];
And you are trying to cast them to T and call it using reinterpret_cast:
reinterpret_cast<T>(m_functions[i])(title,cause,file,line);
However, reinterpret_cast cannot remove const qualifier from a type, therefore, you should first remove the const using const_cast:
reinterpret_cast<T>(const_cast<void*>(m_functions[i]))(title,cause,file,line);
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
However, please note that const_cast engenders undefined behavior and is unsafe. So is calling a function pointer returned from reinterpret_cast if the original pointer was not actually a T.
Edit:
You can call a const qualified function pointer, however, then the reinterpret_cast should contain the const qualifier:
reinterpret_cast<const T>(m_functions[i])(title,cause,file,line);
This is a functor:
class add_x {
int x;
public:
add_x(int x) : x(x) {}
int operator()(int y) { return x + y; }
};
And from main I can do this:
add_x add10(10); // create my functor
int i = add10(20); // add 20 and return it
How can I combine the functor with typedef?
For instance, I came across this:
typedef int (*myfuncType)(float f, char c1,char c2);
myfuncType pt2Function = NULL;
But what am I defining here exactly? operator ()?
Function pointer is - as its name says - just a pointer to function. You cannot use a pointer to function to point to functor, which is essentially a class with overloaded () operator.
You may be interested in std::function from C++11:
#include <functional>
(...)
std::function<int(int)> fn = add_x(10);
int i = fn(20);
Edit: Ok, I see, what you are asking for.
Maybe some code will make things clear.
int fn(float a, char b, char c) { ... }
(...)
typedef int (*myFuncType)(float f, char c1, char c2);
myFuncType ptrToFun = &fn;
(*fn)(1.0f, 'a', 'z');
This typedef creates a "pointer-to-function" type. If you declare a variable of this type, then you'll be able to assign to it a pointer to function (extracted with regular & operator) and - for example - pass to another function or just store (or call this function).
std::function is a lot more flexible, because you can store in it a pointer to function, a functor or even a lambda and call them normally.
I don't understand your first question (How can I combine the functor with typedef ?), so I can't answer that - a typedef would work as it would with any other class.
Regarding your second question: the line
typedef int (*myfuncType)(float f, char c1,char c2);
gives a name (myfunctType) to the type int (*)(float, char, char) (read: "a function which takes a float and two char values and then returns an int").
So
myfuncType pt2Function = NULL;
Defines a variable which can point to such an above-mentioned function, but sets the pointer to NULL for now.
Here, myfuncTypeis a type describing a pointer of function, with three float parameters and which return an int. A functor is just a class with operator() overload. So the typedef is used just like other class.
typedef add_x add will work.
What would typedef int (&rifii) (int, int) be used for?
What is the typedef before this "statement" do?
I want to think of this as
typedef (int (&rifii) (int, int)) [new name]
but the [new name] is not there like if you do
typedef int INTEGER;
Similar question for the following syntax:
typedef void (*PF) ();
PF edit_ops[ ] = { &cut, &paste, ©, &search };
PF file_ops[ ] = { &open, &append, & close, &write };
PF* button2 = edit_ops;
PF* button3 = file_ops;
button2[2]( );
What is the typedef allowing? Is it making it so you don't have to type:
void (*PF) ();
(void (*PF) ()) edit_ops[ ] = { &cut, &paste, ©, &search };
(void (*PF) ()) file_ops[ ] = { &open, &append, & close, &write };
(void (*PF) ())* button2 = edit_ops;
(void (*PF) ())* button3 = file_ops;
If so what happend to the second part ([what you want]) of the typedef like in:
typedef [what you have -- (FP)] [what you want]
Clarification on this matter is greatly appreciated.
Typedef does not work like typedef [type] [new name]. The [new name] part does not always come at the end.
You should look at it this way: if [some declaration] declares a variable, typedef [same declaration] would define a type.
E.g.:
int x; declares a variable named x of type int -> typedef int x;
defines a type x as int.
struct { char c; } s; defines a variable named s of some struct type -> typedef struct { char c; } s; defines type s to be some struct type.
int *p; declares a variable named p of type pointer to int ->
typedef int *p; defines a type p as pointer to int.
And also:
int A[]; declares an array of ints named A -> typedef int A[]; declares a type A as an array of ints.
int f(); declares a function named f -> typedef int f(); declares a function type f as returning an int and taking no arguments.
int g(int); declares a function name g -> typedef int g(int); declares a function type g as returning an int and taking one int.
As an aside: Note that all function arguments come after the new name! As those types could be complicated as well, there can be a lot of text after the [new name]. Sadly, but true.
But those are not proper function pointers yet, just function types. I'm not sure a function type exists in C or C++, but it is useful as an intermediate step in my explanation.
To create a real function pointer, we have to add '*' to the name. Which, sadly, has wrong precedence:
typedef int *pf(); declares a function type pf as return a int*. Oops, that's not what was intended.
So use () to group:
typedef int (*pf)(); declares a function pointer type pf as returning an int and taking no arguments.
typedef int (&rf)(); declares a function reference type rf as returning an int and taking no arguments.
Let's now look at your examples and answer your questions:
typedef int (&rifii) (int, int); declares a function reference type rifii as returning an int and taking two int arguments.
And obviously (?) button2[2]( ); will call copy();.
Proper syntax without typedefs is hard to write correctly without a compiler, and hard to read even with a compiler:
void (*edit_ops[])() = { &cut, &paste, ©, &search };
void (*file_ops[])() = { &open, &append, & close, &write };
void (**button2)() = edit_ops;
void (**button3)() = file_ops;
button2[2]( );
Which is why everyone prefers typedefs when using function pointers.
When reading, find the place to start reading. Read as much to the right as you can, but observe the grouping by (). Then read to the left as much as you can, again limited by grouping (). After finishing everything inside the (), start with reading to the right, then to the left.
Applied to void (*edit_ops[])(), this means that
edit_ops is
(go to the right)
an array
(hit the end of the group, so turn to the left)
of pointer
(end of grouping)
to a function taking
(parse the () to the right)
no arguments
(go to the left)
returning a void
For the experts:
To make it even more complicated, arguments can have names (which will be ignored), so it might even be hard to find where to start parsing! E.g. typedef int (*fp)(int x); is valid and the same as typedef int (*fp)(int); Names can even have () around them: typedef int (*fp)(int (x)); But as we have seen, argument names can be left out, so even the following is allowed: typedef int (*fp)(int ());. This is still a function pointer taking a single int and return an int. In case you would like to make your code really hard to read...
edit: sorry first answer didn't initialize the fcn ptr.
typedef int (&rifii) (int, int) allows you to declare function pointers that return an int by reference and take two ints as parameters.
rifi x,y,z;
int &ret_an_int_ref( int p1, int p2 ) {
static int retval=0;
if( p1 > p2 ) retval = p1*p2;
return retval;
}
x = ret_an_int_ref;
y = ret_an_int_ref;
int & an_int_ref = x(1,2);
int & another_int_ref=y(3,4);
z = x;
z(1,2); // will give the same answer as x(1,2);
I'm trying to implement an observer pattern (of sorts) with C++ and I want to use function pointer to do so, but I keep getting an error when trying to cast a function pointer from class B to a typedef function pointer:
#include <map>
typedef int (*OutputEvent)(const char*, const char*, int);
class A
{
private:
int nextListenerId;
std::map<int, OutputEvent> listenerMap;
public:
A(){ nextListenerId = 0;}
~A(){}
inline int RegisterListener(OutputEvent callback)
{
nextListenerId++;
listenerMap[nextListenerId] = callback;
return nextListenerId;
}
};
class B
{
private:
int listenerId;
public:
B(const A& a)
{
OutputEvent e = &B::CallMeBack;
listenerId = a.RegisterListener(e);
}
~B(){}
int CallMeBack(const char* x, const char* y, int z)
{
return 0;
}
};
I created this example and I've pasted it into codepad.org, but when I it fails to compile (it doesn't compile in codepad.org nor in Visual Studio 2010):
Output:
t.cpp: In constructor 'B::B(const A&)':
Line 28: error: cannot convert 'int (B::*)(const char*, const char*, int)' to 'int (*)(const char*, const char*, int)' in initialization
compilation terminated due to -Wfatal-errors.
I don't understand why it can't convert the function pointers. Could anybody help me please?
The function you are trying to cast to OutputEvent is a member function. This is represented clearly in the error message by this:
'int (B::*)(const char*, const char*, int)'
which is a different type than
int (*OutputEvent)(const char*, const char*, int)
because of the B:: part (that means that the function has an invisible this parameter).
If you define your member function as static, then you will be able to cast it to OutputEvent:
class B
{
....
static int CallMeBack(const char* x, const char* y, int z);
...
};
The member function doesn't match the typedef'd prototype because member functions have an invisible 'this' parameter. Make it a static function and it should work.
The class member function has got a hidden parameter, the object, which the global function does not have.
Do something like this:-
B*pB;
int CallMeBack(const char* x, const char* y, int z)
{
return pB->CallMeBack(x,y,z);
}
More difficult if you have several callbacks on the go at the same time. But if there is only one you can have a pointer to the object and call via this.
Can you please explain what does the following line means?
typedef int (*Callback)(void * const param,int s)
It means that Callback is a new name for the type : pointer to a function returning an int and taking two parameters of type 'const pointer to void' and 'int'.
Given a function f :
int f(void * const param, int s)
{
/* ... */
}
The Callback can be used to store a pointer to f :
Callback c = &f;
The function f can be later invoked through the pointer without directly referring to its name :
int result = c(NULL, 0);
At the point of the call, the name f does not appear.
It creates a new "alias" or name by which you can refer to pointers to functions that return int and take two parameters: a void* const and an int. You can then create variables of that type, assign to them, invoke the function through them etc as in:
int fn(void * const param,int s) { ... }
Callback p;
p = fn;
int x = p(NULL, 38);
Note that typedefs do not really create new types... every equivalent typedef is resolved to the single real type for the purposes of overload resolution, template instantiation etc..
It declares a function type:
// Set up Callback as a type that represents a function pointer
typedef int (*Callback)(void * const param,int s);
// A function that matches the Callback type
int myFunction(void* const param,int s)
{
// STUFF
return 1;
}
int main()
{
// declare a variable and assign to it.
Callback funcPtr = &myFunction;
}