consider the Utility class below:
It will contain lots of factory methods with same signature int function(int a, int b);
Utility.h
class Utility
{
public:
template<typename T, typename A, typename B>
static int get_function(T% function, int% number)
{
function = (T) add;
number = 10;
return 0;
}
static int add (int a, int b) {
return a+b;
}
};
this contains a template method (get_function()) to assign Function pointers from factory methods available in Utility class.
Main.cpp
typedef int (__stdcall *FP) (int a, int b);
ref class FPClass
{
public:
static FP fp;
static int number;
static void apply_function()
{
Utility::get_function<FP, int, int>(FPClass::fp, number);
cout << FPClass::fp(25, 45);
}
};
void main()
{
FPClass::apply_function();
}
What I want to achieve is, to assign the function pointer (FPClass::fp) by the template method (Utility:get_function).
But the function pointer parameter is not modified (always null) by the called function (Utility:get_function).
why is that?
Related
I was wondering if there's a way to optimize/reduce this logic? As the number of the variables increases, the number of the parameters increases as well, which can make the code a bit messy.
.h file
class ClassA
{
public:
ClassB type1_1;
ClassB type1_2;
ClassB type1_3;
// ... There can be more than this
ClassB type2_1;
ClassB type2_2;
ClassB type2_3;
// ... There can be more than this
void SetType1(ClassB a, ClassB b, ClassB c);
void SetType2(ClassB a, ClassB b, ClassB c);
__forceinline vector<ClassB> GetListofType1() { return list_type1; }
__forceinline vector<ClassB> GetListofType2() { return list_type2; }
private:
vector<ClassB> list_type1;
vector<ClassB> list_type2;
};
.cpp file
// ... As the number of type1 variables increases, the number of parameters increases
void ClassA::SetType1(ClassB a, ClassB b, ClassB c)
{
type1_1 = a;
type1_2 = b;
type1_3 = c;
list_type1.push_back(a);
list_type1.push_back(b);
list_type1.push_back(c);
}
// ... As the number of type2 variables increases, the number of parameters increases
void ClassA::SetType2(ClassB a, ClassB b, ClassB c)
{
type2_1 = a;
type2_2 = b;
type2_3 = c;
list_type2.push_back(a);
list_type2.push_back(b);
list_type2.push_back(c);
}
Use initializer lists:
#include <cassert>
#include <vector>
struct ClassB { };
class ClassA {
public:
static constexpr int list_type1_len = 3;
inline void SetType1(const std::vector<ClassB>& set_type_1){
assert(set_type_1.size()==3);
list_type1 = set_type_1;
}
inline std::vector<ClassB>& GetListofType1() { return list_type1; }
private:
std::vector<ClassB> list_type1;
};
int main(){
ClassA a;
a.SetType1({ClassB(), ClassB(), ClassB()});
return 0;
}
If the number of elements is known at compile time, you may be able to solve your code duplication problem using variadic templates and tuples or arrays.
For example:
#include <iostream>
#include <array>
template <typename T, unsigned N1, unsigned N2>
class ClassA {
public:
std::array<std::array<T,N2>,N1> xs { };
template <unsigned N, typename... X>
void SetType(X&&... x) {
std::get<N>(xs) = { std::forward<X>(x)... };
}
template <unsigned I1, unsigned I2>
T& get() {
return std::get<I2>(std::get<I1>(xs));
}
};
int main(int argc, char* argv[]) {
ClassA<int,2,3> a;
a.SetType<0>(1,2,3);
std::cout << a.get<0,1>() << std::endl;
}
How to create a function pointer to any class function knowing only arguments and return type? How to call this function later?
I read about std::function, however I do not have an idea how to implement it without using specific class name like "std::function<void(const ClassName&, int)> f_add_display = &ClassName::func;"
The example below is NOT for compiling, it is only to show the idea I mean:
class collection {
p* ...; //pointer to any(!) class function with known arguments and return type
} _collection;
class One {
public:
...
bool Foo_1(int, int) {};
void saveFuncAddr() {_collection.p = this::Foo_1};
};
class Two {
public:
bool Foo_2(int, int) {};
void saveFuncAddr() {_collection.p = this::Foo_2};
};
int main() {
one* = new One();
one->saveFuncAddr();
bool res1 = (*_collection.p)(1, 2);
two* = new Two();
two->saveFuncAddr();
bool res2 = (*_collection.p)(1, 2);
}
First, identifiers beginning with an underscore is reserved in the global namespace, so you shouldn't declare a name like _collection.
You can use lambdas to wrap your member functions:
#include <functional>
struct Collection {
std::function<bool(int, int)> p;
} collection;
class One {
public:
bool Foo_1(int, int) {return true;}
void saveFuncAddr()
{
collection.p = [this](int a, int b){return this->Foo_1(a, b);};
}
};
class Two {
public:
bool Foo_2(int, int) {return true;}
void saveFuncAddr()
{
collection.p = [this](int a, int b){return this->Foo_2(a, b);};
}
};
int main() {
auto one = new One();
one->saveFuncAddr();
bool res1 = (collection.p)(1, 2);
delete one;
auto two = new Two();
two->saveFuncAddr();
bool res2 = (collection.p)(1, 2);
delete two;
}
I am trying pass the function as an argument, the Testabc is inherited from MainTest and the function I want to pass is protected function in MainTest class. I do not have the cpp access to the MainTest class which has this protected ReadTestPoint function.
Below is header file where I define the function that is taking the function as an argument.
#include <QObject>
#include <QDebug>
class TestManager
{
public:
TestManager();
~TestManager() {}
int ReadTestPointer(void *dp, unsigned int &val, int (*functioncall)(void *,
unsigned int&));
};
Below is the cpp for the TestManager
#include "testmanager.h"
#include<QDebug>
TestManager::TestManager(){}
int TestManager::ReadTestPointer(void* dp, unsigned int &num, int (*readt)
(void*, unsigned int&))
{
qDebug()<< "Function Pointer working";
int g;
g = (*readt)(dp, num);
return g;
}
The class from where I am making the call:
namespace PackageCore
{
TestAbc::TestAbc() : MainTest(){}
TestAbc::~TestAbc(){}
int TestAbc::Init()
{
// initialization code called once
m_config = reinterpret_cast<Test_BaseClass*>
(GetConfig(Test_BaseClass_INTERFACE_HASH));
return 0;
}
int TestAbc::DeInit()
{
return 0;
}
int TestAbc::Cycle()
{
TestManager m_TestManager;
unsigned int m_trigger;
int (*abc)(void *, unsigned int&) = ReadTestPoint(m_config-
>SHM_B_Trigger_U8, m_trigger);
m_TestManager.ReadTestPointer(m_config->SHM_B_Trigger_U8, m_trigger, abc);
qDebug()<< " getTrigger: " << m_trigger;
return 0;
}
}
But I get the compile time error on this:
C:\test_manager_git\testabc.cpp:39: error: invalid conversion from 'int' to 'int (*)(void*, unsigned int&)' [-fpermissive]
int (*abc)(void *, unsigned int&) = ReadTestPoint(m_config->SHM_B_Trigger_U8, m_trigger);
The MainTest.h is below:
class MainTest : public QObject
{
Q_OBJECT
public:
// Callbacks
virtual int Init() = 0;
virtual int Cycle() = 0;
virtual int DeInit() = 0;
protected:
int ReadTestPoint (void *dp, unsigned int &val);
};
Thanks
First of all, consider using things like std::function instead of rolling your own pointer nightmare. But lets get started...
Basically, in order to call a member function from pointer, you need the function pointer and a member instance. The following code is based on your question code with the added member pointer.
#include <iostream>
class MainTest
{
public:
protected:
int ReadTestPoint (void *dp, unsigned int &val)
{
std::cout << "protected ReadTestPoint called" << std::endl;
return 0;
}
};
class TestManager
{
public:
TestManager() {}
~TestManager() {}
int ReadTestPointer(void *dp, unsigned int &val, MainTest* instance, int (MainTest::*functioncall)(void *, unsigned int&))
{
return (instance->*functioncall)(dp, val);
}
};
class TestAbc : public MainTest
{
public:
void ExecTest()
{
TestManager testManager;
unsigned int tVal;
void* dummy = &tVal;
testManager.ReadTestPointer(dummy, tVal, this, &TestAbc::ReadTestPoint);
}
};
int main(void)
{
TestAbc test;
test.ExecTest();
return 0;
}
If you don't want to restrict yourself to a specific member type, consider using a template function:
class TestManager
{
public:
TestManager() {}
~TestManager() {}
template<typename Fn>
int ReadTestPointer(void *dp, unsigned int &val, Fn functioncall)
{
return functioncall(dp, val);
}
};
It will accept non-member functions and objects that overload the operator() with appropriate parameters and return types.
You can wrap the member function pointer in a Functor object:
template<typename TMember, typename TResult, typename TParam1, typename TParam2>
struct Functor
{
typedef TResult (TMember::*TFn)(TParam1, TParam2);
Functor(TMember* m, TFn func):member(m), fn(func){}
TMember* member;
TFn fn;
TResult operator()(TParam1 p1, TParam2 p2)
{
return (member->*fn)(p1, p2);
}
};
The following example includes a free function call and a member function call:
int FreeFn(void *dp, unsigned int &val)
{
std::cout << "free function called" << std::endl;
return 1;
}
class TestAbc : public MainTest
{
public:
void ExecTest()
{
TestManager testManager;
unsigned int tVal;
void* dummy = &tVal;
testManager.ReadTestPointer(dummy, tVal, Functor<TestAbc, int, void*, unsigned int&>(this, &TestAbc::ReadTestPoint));
testManager.ReadTestPointer(dummy, tVal, FreeFn);
}
};
I am trying to declare a class-member function pointer as static so it can be called by a static member function, and assign the pointer to a function passed to the constructor.
So far I haven't been able to get it working, is this somehow possible?
#include <stdio.h>
//external callback function
static void innerFunc(int i, float f){
printf("running inner function : %i %f\n", i, f);
}
class A{
// member function pointer
typedef void (A::*cbPtr)(int, float);
static cbPtr cbptr;
public:
//constructor
A(void(*func)(int, float))
{
A::cbptr = func; // < this doesn't work
}
void run()
{
memberFunc(5, 4.4, NULL, NULL);
}
private:
// static member function
static void memberFunc(int i, float f, void* a, const void* aa)
{
printf("running outer function.\n");
// cbptr(i, f); // << I want to be able to call the function here
}
};
int main() {
A a(innerFunc);
a.run();
return 0;
}
The A::cbPtr type expects a pointer to a non-static member function of the A class. But you are trying to assign a pointer to a non-member function to your static cbptr variable. They are two different types, that is why the code does not compile.
Drop the A:: from your cbPtr typedef, eg:
#include <stdio.h>
//external callback function
static void innerFunc(int i, float f)
{
printf("running inner function : %i %f\n", i, f);
}
class A
{
public:
// non-member function pointer
typedef void (*cbPtr)(int, float);
//constructor
A(cbPtr func)
{
m_cbptr = func;
}
void run()
{
memberFunc(5, 4.4, NULL, NULL);
}
private:
static cbPtr m_cbptr;
// static member function
static void memberFunc(int i, float f, void* a, const void* aa)
{
printf("running outer function.\n");
m_cbptr(i, f);
}
};
A::cbPtr A::m_cbptr = NULL;
int main()
{
A a(innerFunc);
a.run();
return 0;
}
When you learn how to separate your declarations and definitions into .h and .cpp files, it would look more like this instead:
A.h:
#ifndef A_H
#define A_H
class A
{
public:
// non-member function pointer
typedef void (*cbPtr)(int, float);
//constructor
A(cbPtr func);
void run();
private:
static cbPtr m_cbptr;
// static member function
static void memberFunc(int i, float f, void* a, const void* aa);
};
#endif
A.cpp:
#include "A.h"
#include <stdio.h>
A::cbPtr A::m_cbptr = NULL;
A::A(A::cbPtr func)
{
m_cbptr = func;
}
void A::run()
{
memberFunc(5, 4.4, NULL, NULL);
}
void A::memberFunc(int i, float f, void* a, const void* aa)
{
printf("running outer function.\n");
m_cbptr(i, f);
}
main.cpp:
#include "A.h"
#include <stdio.h>
//external callback function
static void innerFunc(int i, float f)
{
printf("running inner function : %i %f\n", i, f);
}
int main()
{
A a(innerFunc);
a.run();
return 0;
}
Either way, just know that because m_cbptr is static, multiple instances of A will share the same variable, so you won't be able to have separate callbacks for different A objects. If memberFunc() were not static, or if its a or aa parameter is a user-defined value that can be set to point at the A object's this pointer, then you can have a separate callback per object.
I've got a class D, that I want to have classes A,B,C inherit from. However, the functions that I want to declare as pure virtual are templated.
Unfortunately, in the words of visual studio:
member function templates cannot be virtual
Classes A,B,C have a member operator called in the exact same manner, though may return different values (double or unsigned int namely. But I'd be happy to get it to work with just double):
template<typename T>
double operator()(T&, unsigned int b){/*code*/};
How could I properly create a polymorphic collection of classes A,B,C (similar to a std::vector<D*> that would work if I didn't want member function templates) that does what I'm trying to do?
EDIT:
An example of what I'd like to be able to do:
std::default_random_engine rng((unsigned int) std::time(0));
std::vector<D*> v;
v.push_back(new A(0.3));
v.push_back(new B(1.0,3.2));
v.push_back(new C);
for(auto x : v){
for(auto y : x->operator()(rng,5){
std::cout << y << ',';
}
std::cout << std::endl;
}
I'm not entirely sure what you want to do, but if you move the template definition to the class instead of the method, everything is happy. Does that do what you want?
template<typename T>
class A
{
public :
virtual double operator() (T& t, unsigned int b) = 0;
};
template<typename T>
class B : public A<T>
{
public:
virtual double operator() (T& t, unsigned int b)
{
// code
}
};
EDIT:
Or, given that you don't want the template at the class level, what about moving the random calculation out of the polymorphic method, and then having a simple plymorphic method for the actual hard part. This assumes you only want to generate one random number, If you want more, you could always create a vector of random numbers, the size of which is determined in construction. Anyway the code below demonstrates what I am talking about:
class D
{
public :
template<typename T>
double operator() (T& t, unsigned int b)
{
double calc_rand = t();
return DoStuff(calc_rand, b);
}
protected :
virtual double DoStuff(double rnd_value, unsigned int b) = 0;
};
class A : public D
{
protected :
virtual double DoStuff(double rnd_value, unsigned int b)
{
return rnd_value * b;
}
};
int main(void)
{
std::random_device rd;
A a;
std::cout << a(rd, 5) << std::endl;
}
You'll most probably need to use delegates here. If all the classes have the same name and parameters, it's as easy as doing:
template <typename T>
class baseWrapper{
double method(T& a, unsigned int b) = 0;
};
template <typename T, typename myClass>
class wrapper: public baseWrapper<T>{
myClass &instance;
double method(T& a, unsigned int b){
return instance.method<T>(a,b);
};
wrapper(myClass &instance){this->instance = instance;};
};
And then you can create a collection of delegates:
std::vector<baseWrapper<int>*> vec;
A myObject1, B myObject2;
wrapper<int,A> wrapper1(myObject1);
wrapper<int,B> wrapper2(myObject2);
vec.push_back(&wrapper1);
vec.push_back(&wrapper2);
If the functions are named differently, you'll need to pass a function pointer as an additional parameter, or test it with SFINAE.
Perhaps you can implement a type erasure for the template parameter of the member functions. Going with your RNG example:
class RandUIntIfc {
public:
virtual ~RandUIntIfc() = 0;
virtual unsigned int min() const = 0;
virtual unsigned int max() const = 0;
virtual unsigned int operator()() = 0;
};
class RandUInt {
public:
template <typename RNG>
explicit RandUInt(RNG& rng);
unsigned int min() const;
unsigned int max() const;
unsigned int operator()();
private:
std::shared_ptr<RandUIntIfc> impl_;
template <typename RNG>
class Impl : public RandUIntIfc {
public:
explicit Impl(RNG& rng);
virtual unsigned int min() const;
virtual unsigned int max() const;
virtual unsigned int operator()();
private:
RNG& ref_;
};
};
I hope all the actual member definitions are obvious. That leaves just the change to D and code that uses it:
class D {
public:
virtual ~D() = 0;
virtual double operator()(RandUInt rng, unsigned int b) = 0;
};
std::default_random_engine rng((unsigned int) std::time(0));
RandUInt typeless_rng(rng);
std::vector<D*> v;
// ...
for(auto x : v){
for(auto y : x->operator()(typeless_rng,5){
std::cout << y << ',';
}
std::cout << std::endl;
}
You shouldn't use a template function but just pass delegate to the rng through the virtual function. So basically you could do this:
class D
{
virtual double operator()(std::function<int()>, int)=0;
};
And call it like this:
std::default_random_engine rng;
std::vector<D*> v;
...
for(auto x : v)
{
std::cout << x->operator(std::bind(rng), 5) << ',';
}