Pointer static method that points to no static method - c++

I've been trying to make a pointer function that points to a method doing something like this(visual C++):
struct test
{
int tst(int a)
{
return a * 4;
}
};
// ok, this the visual C++ compiler does not accept it... (mingw accept it)
int(*tstptr)(int) = (int(*)(int))&test::tst;
Then I've done something like this:
struct Dx
{
int SomeMethod()
{
return 4;
}
};
struct Dy
{
static int(*pSomeMethod)();
};
int(Dy::*pSomeMethod)() = (int( Dy::*)())&Dx::SomeMethod;
So far so good, this compiles without problems, but if I try call her:
Dy::pSomeMethod();
The compiler returns me:
Error 1 error LNK2001: external symbol "public: static int (__stdcall
* Dy::pSomeMethod) (void)" (? PSomeMethod#Dy##2P6GHXZA) unresolved
which I do not understand, because it is not suppose pSomeMethod he is not pointing at SomeMethod ?

The type of &test::tst is int (test::*) (int), which is a member function pointer.
You are trying to convert it to a regular pointer type, which is not possible because they are completely different.
That's why you will have this type cast error:
error C2440: 'type cast' :
cannot convert from 'int (__thiscall test::* )(int)' to 'int (__cdecl *)(int)'

int(Dy::*pSomeMethod)() = (int( Dy::*)())&Dx::SomeMethod;
Type Checked, so no complain from compiler.
As for:
Dy::pSomeMethod();
This a __cdecl.
But, SomeMethod is a __thiscall, which means it's really like this
int SomeMethod( Dx &this);
So, linker can't find a match.
You simply can't call non-static method without object of class Dx.

Your declaration of pSomeMethod defines a pointer to a function within class Dy that returns an int. You want to declare it as it appears in the linker error:
int (*Dy::pSomeMethod)();
which is a member of Dy that is a pointer to a function returning an int.
What you're trying to do won't work, since Dx::SomeMethod is a member function of Dx, which needs a this pointer. Calling thru pSomeMethod won't have one.
When done right, you can just assign the address of the function to the pointer without using a cast.

Related

Need to assign pointer to a function generated from a function template (Visual Studio 2015)

I have a function that takes following arguments as below -
int X::MainFun(Pfn, void*,int)
and Pfn is defined as
int (*Pfn) (int*, void*, int);
Now I have a function template as follows :
template <typename IntfType>
static int MasterOps(int * pRec, void* pSt, int pOffset ){
IntfType* IfObj = (IntfType*) (((MasterOpArgs*)pSt)->vIfObj);
if(IfObj->MasterOps(pRec, pSt, pOffset) == MIGINTF_SUCC) return 1;
else return 0;
}
Now I am calling function MainFun as -
MasterOpArgs margs;
Xobj->MainFun(MasterOps<MigT>, &margs,0 );
type MigT is a class defined earlier which implements a member MasterOps and MainFun() is actually a member function of some class.
Definition of template and call for MainFun() is happening in same file.
I assumed that call to MainFun would also cause instantiation of function template MasterOps with type MigT, but it seems I am wrong as I see following errors
error C2440: 'type cast': cannot convert from 'overloaded-function' to 'Pfn': note: None of the functions with this name in scope match the target type
error C2059: syntax error: ','

How to pass method(as callback) as param to method?

I have static method in my Utils class
This is definition
/*static*/ void Utils::copy_files(void(*progress_callback)(int, int),
std::string const & path_from,
std::string const & path_to)
{
....
}
And here using
void TV_DepthCamAgent::progress_callback(int count, int copied_file)
{
printf("Progress :: %d :: %d\n", count, copied_file);
}
void TV_DepthCamAgent::foo()
{
...
shared::Utils::copy_files(progress_callback, path_from_copy, path_to_copy);
...
}
And this is an errors that I get
E0167 argument of type "void (TV_DepthCamAgent::)(int count, int copied_file)" is incompatible with parameter of type "void ()(int, int)"
Error C3867 'TV_DepthCamAgent::progress_callback': non-standard syntax; use '&' to create a pointer to member
What am I doing wrong?
Since you've tagged this C++ i'm assuming you want a C++ solution.
Since C++11 we can use std::function instead of the awkward C style pointer-to-function syntax.
So void(*progress_callback)(int, int) becomes std::function<void(int, int)> progress_callback
In regards to why you get that error it is because to pass a function pointer you must pass the function by reference
...
shared::Utils::copy_files(&progress_callback);
...
You must then pass the required arguments when you call it in copy_files.
You should use std::function and std::bind for this instead of the C style you seem to be writing in

gluTessCallback error C2440

I am trying to use the function gluTessCallback but I get C2440 error. I have no idea why.
Here is the code:
#define callback void(CALLBACK*)()
template<typename T>
class Tessellation
{
private:
GLUtesselator *pTess;
void CALLBACK tessError(GLenum error)
{
sendErrorMessage((char *)gluErrorString(error), true);
}
public:
void Triangulation3D(T* & point, short numOfPoints)
{
pTess = gluNewTess();
gluTessCallback(pTess, GLU_TESS_ERROR, (callback)tessError);
}
};
The error is on gluTessCallback function:
error C2440: 'type cast' : cannot convert from 'overloaded-function' to 'void (__stdcall *)(void)'
Why do I get this compile error?
The error id C2440 on Visual Studio is a type conversion error.
The problem in your code is that you are trying to pass a class method Tessellation::tessError() as function pointer to gluTessCallback(), which expects a pointer to a global C-style function.
A class method is very different from a free/global function and you cannot pass it as a simple function pointer because it needs an object to go along with it every time, the this pointer.
A solution to your problem would be to declare tessError() as a static method, making it effectively the same as a free/global function scoped inside the class, like so:
template<typename T>
class Tessellation
{
private:
static void CALLBACK tessError(GLenum error)
{
sendErrorMessage((char *)gluErrorString(error), true);
}
...
And pass it to gluTessCallback():
gluTessCallback(pTess, GLU_TESS_ERROR, (callback)&Tessellation<T>::tessError);
The only downside to this approach is that a static tessError() can no longer access class variables. Which doesn't seem like a problem to you, since it is not doing so right now, it appears.

brace initialized function pointer array: invalid conversion from 'void (*(*)())()' to 'void (*)()'

In my arduino sketch I need an array of function pointers with the signature void foo().
I'm using the ino command line utillity on linux (which uses avr-g++ under the hood).
However I'm getting a very strange error while defining the array.
error:
error: invalid conversion from ‘void (* (*)())()’ to ‘void (*)()’
in this piece of code
void (*mode_setup[])(void) = {
&show_time_setup,
&set_time_setup,
&set_alarm_setup,
&set_date_setup // <-- generates 3 identical error on this line
};
I don't understand what I'm doing wrong, since... int foo[] = { 1, 2, 3 }; ..is perfectly valid, and void (*foo)(void) is the syntax for function pointer.
what am I missing?
edit: NEVERMIND IM STUPID
the functions were not void foo(), but fptr foo() [fptr=function pointer typedef]
sincere appologies for wasting peoples time
I can reproduce your error message with this code
void (*foo())() {}
void (*arr[])(void) = { &foo };
So it looks like the signature of the function(s) is not what you think it is. An array to hold a pointer to foo would need to be declared like this:
void (*(*arr[])())(void) = {
&foo
};
If I were you, I'd consider typedefs...

use external function as member-function pointer

Is it possible in C++ to create a function which is not defined in class A but can be treated like a method pointer? Eg.:
typedef bool (A::*MethodType)(int a);
MethodType g_someMethod = &A::SomeMethod;
Now, I want to create a new function AnotherMethod which is of the type MethodType. I have tried to do the following:
bool A_AnotherMethod(A* _this, int a) {
std::cout << __FUNCTION__ << "\n";
return true;
}
MethodType g_someMethod = A_AnotherMethod;
// ...
(this->*g_someMethod )(42);
But I get
error C2440: '=' : cannot convert from 'bool (__cdecl *)(A *,int)' to 'bool (__cdecl A::* )(int)'
How to do it correctly?
No, you can't. C++ does not have a feature similar to extension methods in C#.
p.s. Method pointers have clumsy syntax in C++ and are rarely used. But this is the way how they are defined in the language.