How to define a function pointer pointing to a static member function? - c++

#include "stdafx.h"
class Person;
typedef void (Person::*PPMF)();
// error C2159: more than one storage class specified
typedef static void (Person::*PPMF2)();
class Person
{
public:
static PPMF verificationFUnction()
{
return &Person::verifyAddress;
}
// error C2440: 'return' : cannot convert from
// 'void (__cdecl *)(void)' to 'PPMF2'
PPMF2 verificationFUnction2()
{
return &Person::verifyAddress2;
}
private:
void verifyAddress() {}
static void verifyAddress2() {}
};
int _tmain(int argc, _TCHAR* argv[])
{
Person scott;
PPMF pmf = scott.verificationFUnction();
(scott.*pmf)();
return 0;
}
Question: I need to define a function pointer PPMF2 to pointing to a static member function verifyAddress2. How can I do it?
#include "stdafx.h"
class Person;
typedef void (Person::*PPMF)();
typedef void (Person::*PPMF2)();
class Person
{
public:
static PPMF verificationFUnction()
{
return &Person::verifyAddress;
}
PPMF2 verificationFUnction2()
{
return &Person::verifyAddress2;
}
private:
void verifyAddress() {}
static void verifyAddress2() {}
};
int _tmain(int argc, _TCHAR* argv[])
{
Person scott;
PPMF pmf = scott.verificationFUnction();
(scott.*pmf)();
return 0;
}

A pointer to a static member function is just a normal function pointer. typedef void (*PPMF2)(). You assign it to a static member function like you assign any function pointer, only that the static member function is inside the class scope:
PPMF2 myfunc = &MyClass::StaticMemberFunc;

About static member function guarantees:
С++ ISO/IEC 14882 2003-10-15 says that
5.2.2 There are two kinds of function call: ordinary function call and member function 57) (9.3) call....
57) A static member function (9.4) is an ordinary function.
Theoretically static-member-functions can have another calling convention.
But standart allow us to leverage on such thing...
Answer:
typedef void (Person::*PPMF2)() => typedef void (*PPMF2)()

If the function is static it does not require a (implicit) this pointer to be invoked. Therefore, a pointer to a static member function is not the same as a member function pointer:
#include "stdafx.h"
class Person;
typedef void (Person::*PPMF)();
typedef /*static*/ void (*PPMF2)();
class Person
{
public:
static PPMF verificationFUnction()
{
return &Person::verifyAddress;
}
PPMF2 verificationFUnction2()
{
return &Person::verifyAddress2;
}
private:
void verifyAddress() {}
static void verifyAddress2() {}
};
int _tmain(int argc, _TCHAR* argv[])
{
Person scott;
PPMF pmf = scott.verificationFUnction();
(*pmf)();
return 0;
}
EDIT:
removed the offending static from the typedef.

#include<iostream>
using namespace std;
class A
{
private:
int x,y;
static int a;
public:
A()
{
x = 10;
y = 11;
}
~A()
{
}
void displayNonStatic()
{
cout<<x<<" "<<y<<endl;
}
void displayStatic()
{
cout<<a<<endl;
}
};
int A::a = 12;
int main()
{
typedef void (A::*NonStatic)(void);
typedef void (A::*Static)(void);
A a1;
NonStatic _nstatic = &A::displayNonStatic ;
Static _static = &A::displayStatic;
// Always make sure that call to the pointer to the member functions is made within the context of the instance.
//Correct way to call the pointer within the context of the instance " a1 " .
(a1.*_nstatic)();
(a1.*_static)();
//Error case given below, the pointer is not called within the context of the instance
// (*_nstatic)(); ->error
// (*_static)(); ->error
getchar();
}
Refer to the link for more information.

Related

How to use custom class pointer comparator inside class being compared

I am trying to use a custom comparator as in the following minimal example:
#include <set>
using namespace std;
struct idComp;
class TestClass
{
public:
int id;
void setId(int i){ id = i; }
int getId(){ return id; }
void test( set<TestClass*, idComp> &s){
//do my stuff
}
void test2(){
set <TestClass*, idComp> s;
}
};
struct idComp
{
bool operator() (TestClass* t1, TestClass* t2) const
{
return t1->getId() < t2->getId();
}
};
int main(int argc, char* argv[])
{
return 0;
}
...but when I try to compile I get the following error relating to the test function:
comp_ref.cpp:12:34: error: ‘idComp’ was not declared in this scope
void test( set<TestClass*, idComp> &s){
^~~~~~
comp_ref.cpp:12:40: error: template argument 2 is invalid
void test( set<TestClass*, idComp> &s){
and this with the addition of test2:
/usr/include/c++/7/bits/stl_tree.h:708:31: error: invalid use of incomplete type ‘struct idComp’
_Rb_tree_impl<_Compare> _M_impl;
Any suggestions of how/where to define idComp so that it is usable by the function test?
Since you have a bit of a circular dependency, you can resolve this by forward-declaring idComp before TestClass:
struct idComp;
class TestClass
{
...
But you can leave the definition of struct idComp where it is.

Static variable inside a template base class

This prints nothing:
#include <iostream>
template <typename Derived>
struct A
{
static int test()
{
std::cout << "test" << std::endl;
return 0;
}
static inline int a = test();
};
struct B : public A<B>
{
};
int main(int argc, char** argv)
{
return EXIT_SUCCESS;
}
But this does:
#include <iostream>
template <typename Derived>
struct A
{
};
struct B : public A<B>
{
static int test()
{
std::cout << "test" << std::endl;
return 0;
}
static inline int a = test();
};
int main(int argc, char** argv)
{
return EXIT_SUCCESS;
}
And also this:
#include <iostream>
struct A
{
static int test()
{
std::cout << "test" << std::endl;
return 0;
}
static inline int a = test();
};
struct B : public A
{
};
int main(int argc, char** argv)
{
return EXIT_SUCCESS;
}
Not sure why or a workaround. I need the 'Derived' type to register it into a static table.
The reason why the first snippet doesn't print anything is that the static variable is not instantiated. You have to use that variable in order to instantiate it.
[temp.inst]/2
The implicit instantiation of a class template specialization causes
the implicit instantiation of the declarations, but not of the
definitions, default arguments, or noexcept-specifiers of the class
member functions, member classes, scoped member enumerations, static
data members, member templates, and friends
As a workaround, you can just use that variable:
int main(int argc, char** argv)
{
(void) B::a;
return EXIT_SUCCESS;
}
Since A is a template class, the static inline function/variable are not actually instantiated from the template unless they are used. Thus, you could do e.g. this:
#include <iostream>
template <typename Derived>
struct A
{
static int test()
{
std::cout << "test" << std::endl;
return 0;
}
static inline int a = test();
};
struct B : public A<B>
{
static inline int b = a;
};
int main(int argc, char** argv)
{
return 0;
}
Demo
The (automatic) solution, as pointed here is to create a constructor that uses the registration variable. Also, the variable will be initialized only if an object is constructed.
#include <iostream>
template <typename Derived>
struct A
{
A()
{
a = 0;
}
static int test()
{
std::cout << "test" << std::endl;
return 0;
}
static inline int a = test();
};
struct B : public A<B>
{
};
int main(int argc, char** argv)
{
B b;
return EXIT_SUCCESS;
}
The 'a = 0' is to avoid a warning of unused variable. Overhead should be minimal.
Demo

I have array of pointers of methods my class, but I cannot call my method. Code are below

#include <iostream>
#include <stdio.h>
#include <stdint.h>
/* run this program using the console pauser or add your own getch, system("pause") or input loop */
class FooBar{
public:
typedef void(FooBar::*OnDio)(void);
void OnDio0Irq( void ){
printf("dio0\n");
};
void OnDio1Irq( void ){
printf("dio1\n");
};
FooBar(){
OnDio dioArray[] = {&OnDio0Irq, &OnDio1Irq};
};
OnDio *dioArray[2];
private:
};
int main(int argc, char* argv[]){
typedef void(FooBar::*OnDio)(void);
void (FooBar::*foo)(void);
OnDio *myPtr;
FooBar *fb = new FooBar();
myPtr = *(&fb->dioArray[0]);
foo = (OnDio &)(myPtr[0]);
(foo)();//me need call fb->dioArray[0]()
(*myPtr)(); // ?
}
How can I call a function from an array?
In my code i have error:
[Error] must use '.' or '->' to call pointer-to-member function in 'foo
(...)', e.g. '(... ->* foo) (...)'
[Error] must use '.' or '->' to call pointer-to-member function in
'* myPtr (...)', e.g. '(... ->* * myPtr) (...)'
To call a pointer to member function (ptmf), you need an instance and the ptmf, together.
OnDio is already typedef'ed to be a pointer type, so you may not want OnDio pointers.
Also, you initialize a local temporary in the constructor, not the dioArray of "this" instance.
This answer is also helpful: C++: Array of member function pointers to different functions
Here is your code, corrected to call dio0 through a pointer to member function.
#include <iostream>
#include <stdio.h>
#include <stdint.h>
class FooBar {
public:
typedef void(FooBar::*OnDio)(void);
void OnDio0Irq(void) {
printf("dio0\n");
};
void OnDio1Irq(void) {
printf("dio1\n");
};
FooBar() {
// declaring a local OnDio array just masks the actual member and then it gets tossed
// need to initialize this instance, not some local temporary
dioArray[0] = &FooBar::OnDio0Irq;
dioArray[1] = &FooBar::OnDio1Irq;
};
OnDio dioArray[2];
private:
};
int main(int argc, char* argv[]) {
// need instance
FooBar fb;
// need pointer to member function
FooBar::OnDio func = fb.dioArray[0];
// call pointer to member function using instance
(fb.*func)();
}
#include <iostream>
#include <stdio.h>
#include <stdint.h>
class FooBar {
public:
typedef void(FooBar::*OnDio)(void);
OnDio dioArray[2];
void OnDio0Irq(void) {
printf("dio0\n");
};
void OnDio1Irq(void) {
printf("dio1\n");
};
FooBar() {
dioArray[0] = &FooBar::OnDio0Irq;
dioArray[1] = &FooBar::OnDio1Irq;
};
private:
};
int main(int argc, char* argv[]) {
FooBar* fb = new FooBar();
for (int i = 0; i < sizeof(fb->dioArray) / sizeof(fb->dioArray[0]); i++)
{
(fb->*fb->dioArray[i])();
}
}

calling functor using function Object tr1::function<>

I try to implement Scott Mayer book code example, the example is about calling functor through function object
the header file gameCharachter.h
#ifndef GAMECHARACTER_H
#define GAMECHARACTER_H
#include <iostream>
#include <typeinfo>
using namespace std;
#include <tr1/functional>
class GameCharacter;
int defaultHealthCalc(const GameCharacter& gc);
class GameCharacter
{
public:
typedef std::tr1::function<int (const GameCharacter&)> HealthCalcFunc;
explicit GameCharacter(HealthCalcFunc hcf = defaultHealthCalc)
: healthFunc(hcf)
{
}
~GameCharacter()
{
}
int healthValue() const
{
return healthFunc(*this);
}
private:
HealthCalcFunc healthFunc;
};
class EyeCandyCharacter: public GameCharacter // another character
{
public:
explicit EyeCandyCharacter(HealthCalcFunc hcf = defaultHealthCalc)
: GameCharacter(hcf)
{
cout<<typeid(*this).name()<<"::"<<__FUNCTION__<<""<<endl;
}
};
struct HealthCalculator
{
/*explicit*/ HealthCalculator()
{
}
int operator()(const GameCharacter& gc) const // calculation function
{
cout<<typeid(*this).name()<<"::"<<__FUNCTION__<<""<<endl;
return 0;
}
};
#endif // GAMECHARACTER_H
the main.cpp is :
#include "gamecharacter.h"
int main()
{
EyeCandyCharacter ecc1(HealthCalculator());
ecc1.healthValue();
}
why function<> object refuse to call the operator() function in healthvalue()
EyeCandyCharacter ecc1(HealthCalculator());
declares a function called ecc1 that takes an argument of type "pointer to function taking no arguments and returning a HealthCalculator" and returns a EyeCandyCharacter. I assume that this isn't your intent.
this is the correct call , it should be called by bind
#include "gamecharacter.h"
int main()
{
HealthCalculator hc;
EyeCandyCharacter ecc1(std::tr1::bind(&HealthCalculator::operator(),hc,tr1::placeholders::_1));
ecc1.healthValue();
}

C++ function pointer as a static member

I cannot figure the syntax to declare a function pointer as a static member.
#include <iostream>
using namespace std;
class A
{
static void (*cb)(int a, char c);
};
void A::*cb = NULL;
int main()
{
}
g++ outputs the error "cannot declare pointer to `void' member". I assume I need to do something with parentheses but void A::(*cb) = NULL does not work either.
I introduced a typedef, which made it somewhat clearer in my opinion:
class A
{
typedef void (*FPTR)(int a, char c);
static FPTR cb;
};
A::FPTR A::cb = NULL;
void (*A::cb)(int a, char c) = NULL;