#include <iostream>
#include <memory>
#include <vector>
template<typename MP>
inline void* getMethodVoidPointer(MP ptr)
{
return *reinterpret_cast<void**>(&ptr);
}
template<typename FP>
inline FP getFunctionPointer(void* p)
{
return reinterpret_cast<FP>(p);
}
template<typename MP>//, typename = std::enable_if_t<std::is_const_v<MP>>>
inline const void* getMethodConstVoidPointer(MP ptr)
{
return *reinterpret_cast<const void**>(&ptr);
}
template<typename FP>//, typename = std::enable_if_t<std::is_const_v<FP>>>
inline FP getConstFunctionPointer(const void* p)
{
return reinterpret_cast<FP>(p);
}
class Object
{
int i_;
public:
int j_;
Object()
: Object(0,0)
{}
Object(int i, int j = 100)
: i_(i),
j_(j)
{}
void printIplusJplusArg(int arg)
{
std::cout << i_ + j_ + arg << '\n';
}
void printIplusJplusArgConst(int arg) const
{
std::cout << i_ + j_ + arg << '\n';
}
};
struct S
{
int x;
};
void f(void* pv)
{
(void)pv;
}
void fi(int* i)
{
std::cout << *i << '\n';
}
int main()
{
int i = 5;
S s;
S* ip = reinterpret_cast<S*>(&i);
//std::cout << ip->x << '\n';
int* pi = &i;
void* pv = pi; // OK; implicit conversion
void* pv2 = (void*)pi; // OK but unnecessary
const int ci = 4;
const int* pci = &ci;
std::cout << typeid(&ci).name() << '\n';
std::cout << typeid(std::addressof(ci)).name() << '\n';
std::cout << typeid(pci).name() << '\n';
const void* vci = &ci;
f(pi); // OK; implicit conversion
f((void*)pi); // OK but unnecessary
//int* pint = pv; // can't convert void* to T* implicitly
int* pint = static_cast<int*>(pv);
std::cout << "function pointer to void*" << '\n';
std::cout << "aka code pointer to data pointer" << '\n';
//////////////////////////////////////////////////////////////////////
// Convert from function pointer to void*
void (*pf)(void*) = &f;
void (*pfi)(int*) = &fi;
int ini = 5;
pfi(&ini);
std::cout << typeid(pf).name() << '\n';
std::cout << typeid(&pf).name() << '\n';
std::cout << typeid(std::addressof(pf)).name() << '\n';
//void* dataPointer = pf; // implicit conversion from fp to void* doesn't work
//void* dataPointers = static_cast<void*>(pf); // doesn't work
void* dataPointerr = reinterpret_cast<void*>(pf); // works
// dataPointerr(&ini); // data pointer cannot be used as a function
auto prf = &f;
//auto& aprf = &f; // this doesn't work
std::cout << typeid(prf).name() << '\n';
void* dataRefPointerr = reinterpret_cast<void*&>(prf);
std::cout << typeid(dataPointerr).name() << '\n';
std::cout << typeid(dataRefPointerr).name() << '\n';
std::cout << typeid(pfi).name() << '\n';
//////////////////////////////////////////////////////////////////////
// convert from void* to function pointer
void* pobj = reinterpret_cast<void*&>(pfi);
using fptr_v_i = void(*)(int*);
fptr_v_i my_fptr_v_i = reinterpret_cast<fptr_v_i>(reinterpret_cast<long long>(pobj)); // assuming 64 bit pointer
std::cout << "pfi type = " << typeid(pfi).name() << '\n';
std::cout << "my_fptr_v_i type = " << typeid(my_fptr_v_i).name() << '\n';
ini = 10;
my_fptr_v_i(&ini);
std::cout << "&pfi=" << &pfi << '\n'; // 000000704CF1F958
std::cout << "&pfi=" << &pfi << '\n'; // 000000704CF1F958
std::cout << "&(*my_fptr_v_i)=" << &(*my_fptr_v_i) << '\n'; // 00007FF6481C10BE
std::cout << "&(*my_fptr_v_i)=" << &(*my_fptr_v_i) << '\n'; // 00007FF6481C10BE
//////////////////////////////////////////////////////////////////////
// convert from method pointer to void* and then to function pointer
Object o{1,2};
o.printIplusJplusArg(3); // 6
void (Object::*mp)(int) = &Object::printIplusJplusArg;
(o.*mp)(3); // 6
// mp is the method pointer
//void* vmp = (void*)mp;
void* vmp = ∓
//(o.*vmp)(3); // illegal vmp has type void*
std::cout << typeid(reinterpret_cast<void(*)(int)>(getMethodVoidPointer(&Object::printIplusJplusArg))).name() << '\n'; // function pointer
std::cout << typeid(getFunctionPointer<void(*)(int)>(getMethodVoidPointer(&Object::printIplusJplusArg))).name() << '\n'; // function pointer - same
void(*fp)(Object*,int) = getFunctionPointer<void(*)(Object*,int)>(getMethodVoidPointer(&Object::printIplusJplusArg));
void(Object::*mptr)(int) = &Object::printIplusJplusArg;
void(*fpalt)(Object*,int) = getFunctionPointer<void(*)(Object*,int)>(getMethodVoidPointer(mptr));
std::cout << "working?" << '\n';
fp(&o,3); // 6
fpalt(&o,3); // 6
// "call" data member
int Object::*mpdata = &Object::j_;
std::cout << o.*mpdata << '\n';
// convert from const method pointer to const void* and then to const fuction pointer
Object oc{1,2};
oc.printIplusJplusArgConst(3); // 6
using CMP = void (Object::*)(int) const;
CMP cmp;
// or:
void (Object::*mpc)(int) const = &Object::printIplusJplusArgConst;
(oc.*mpc)(3); // 6
// mpc is a const method pointer
void* vmpc = &mpc;
//(oc.*vmpc)(3); // illegal vmpc has type const void*
std::cout << typeid(reinterpret_cast<void(*const)(int)>(getMethodConstVoidPointer(&Object::printIplusJplusArgConst))).name() << '\n'; // function pointer
std::cout << typeid(getConstFunctionPointer<void(*const)(int)>(getMethodConstVoidPointer(&Object::printIplusJplusArgConst))).name() << '\n'; // function pointer - same
// remember in all cases, cv-qualifiers are ignored by typeid (that is, typeid(const T) == typeid(T))
void(*const cfp)(Object* const,int) = getConstFunctionPointer<void(*const)(Object* const,int)>(getMethodConstVoidPointer(&Object::printIplusJplusArgConst));
cfp(&oc,6); // 9
std::cout << typeid(cfp).name() << '\n'; // void (__cdecl*)(class Object * __ptr64 const,int) - the constness of cfp is ignored by typeid
return 0;
}