gluTessCallback error C2440 - c++

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.

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: ','

Pointer static method that points to no static method

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.

Assigning function pointer within a class gives value type error in C++

I've got this code within Entity.h, which is inherited by other classes. The idea is that in the inheriting classes can change the function either to avoid inheritance or to modify behavior.
public:
Entity(void)
{
updateFunction = emptyFunction;
};
~Entity(void);
protected:
void emptyFunction(){}
void (*updateFunction)();
The problem is that I get this error on compilation:
Error 2 error C2440: '=' : cannot convert from 'void (__cdecl Entity::* )(void)' to 'void (__cdecl *)(void)' c:\documents and settings\administrator\my documents\visual studio 2010\projects\projectname\[projectname]\Entity.h 16 1 [projectname]
I've looked at tutorials all over again, it's been a while since I learned these stuff, but I cannot see some dissimilarity, what could be going wrong? IntelliSense unrelines the '=' symbol as the point of the mistake. I hope I didn't overlook anything.
Thanks a lot in advance!!
You need to decalre pointer function as:
class Entity{
public:
Entity(void)
{
updateFunction = &Entity::emptyFunction;
// ...
(this->*updateFunction)(); //Call
};
~Entity(void);
protected:
void emptyFunction(){}
void (Entity::*updateFunction)();
};
In fact updateFunction is not a normal function and it's a class member function.

c++ defining a member-function pointer without knowing the type of the object

I know that the title is not very clear but I didn't know how to write it down in one sentence. So the problem is that I want something like this:
void(typeof(this)::*function)(int,int);
I know that is not going to work but I was wandering whether a solution exists for this problem in c++ or not?
Update:
class MainPage
{
public:
MainPage()
{
void (std::remove_reference<decltype(*this)>::*callback)(int, int) = &MainPage::myFunction;
((*this).*callback)(nullptr,nullptr);
}
~MainPage()
{
}
void myFunction(int a, int b)
{
}
}
Errors:
error C2440: 'newline' : cannot convert from 'MainPage *' to 'std::remove_reference<_Ty> *'
error C2647: '.*' : cannot dereference a 'void (__thiscall std::remove_reference<_Ty>::* )(int,int)' on a 'MainPage'
Yes, use decltype:
void (std::remove_reference<decltype(*this)>::type::*function)(int, int);

C++ Garbage collection, templates and operator overriding - can't understand why it throws an error

I am trying to compile a file which defines a garbage collection template and several supporting classes with use of operator overloading. I've tried to run this through MSVC++ 2008, and the compile stops at this particular class:
// (The collector defines gc_object_generic_base which
// inherits from gc_object_generic_base and optionally adds
// collector-specific properties.)
template<class garbage_collector>
class gc_object_base : public garbage_collector::gc_object_collector_base {
public:
gc_object_base() {
garbage_collector::constructing_gc_object_base(this);
}
static void* operator new(size_t sz,
block_construction_locker_base* lock = block_construction_locker<garbage_collector>().get_this())
{
return garbage_collector::allocate(sz, lock);
}
static void operator delete(void* p, block_construction_locker_base* lock) {
return garbage_collector::deallocate(p);
}
static void operator delete(void* p) {
return garbage_collector::deallocate(p);
}
private:
// TODO: are arrays worth implementing?
static void* operator new[](size_t sz) {
assert(0);
return 0;
}
};
Truncated output for brevity's sake:
2>------ Build started: Project: Test, Configuration: Debug Win32 ------
2>Compiling...
2>FlashTest.cc
2>C:\test\gameswf\base\tu_gc.h(133) : error C2059: syntax error : 'string'
2> C:\test\gameswf\base\tu_gc.h(151) : see reference to class template instantiation 'tu_gc::gc_object_base' being compiled
2>C:\test\gameswf\base\tu_gc.h(135) : error C2091: function returns function
2>C:\test\gameswf\base\tu_gc.h(135) : error C2802: static member 'operator new' has no formal parameters
2>C:\test\gameswf\base\tu_gc.h(135) : error C2333: 'tu_gc::gc_object_base::operator new' : error in function declaration; skipping function body
Any ideas on where I should start looking at?
I just had the same pattern of errors in a different project. It seems to happen when someone has done this somewhere:
#define new new(someArgs, someMoreArgs, etc)
It's targeted at simple 'new' expressions, but it breaks down if anyone tries to declare any more 'operator new' thingies.
In the opening lines
template<class garbage_collector>
class gc_object_base : public garbage_collector::gc_object_collector_base {
garbage_collector appears twice here, once as the template parameter and another as an outer-class to gc_object_collector_base, but as it is a template parameter does it not require "typename" here thus:
template<class garbage_collector>
class gc_object_base : public typename garbage_collector::gc_object_collector_base {
There is no mention of string in your code, that I can see. But I would start by ensuring that you first #include <string> before your class delcaration, and then make sure you use std::string as your declarator, rather than just string.