Populating a wrapper class with pass-through methods - c++

I inherited a large rather-old C++98 codebase which is now luckily using C++17. I have an interface in a header file interfaceHeader.h as follows:
struct PluginInterface {
void (*method1)(bool enabled);
void (*method2)(int param1, int param2);
bool (*method3)(const char *path, const int& val);
};
then in another source cpp file:
MyImplementingClass *gClass = new gClass();
void method1(bool enabled) {
gClass->method1(enabled);
}
void method2(int p1, int p2) {
gClass->method2(p1, p2);
}
bool method3(const char *path, const int& val) {
return gClass->method3(path, val);
}
void pupulateInterface(PluginInterface& iface) {
iface.method1 = method1;
iface.method1 = method2;
iface.method1 = method3;
...
}
I don't have control over that global variable nor on the fact that the interface must be a struct of function pointer.
How can I reduce the boilerplate here? I tried using std::bind but it didn't work: a std::function cannot be converted to a C function pointer.

void pupulateInterface2(PluginInterface& iface) {
iface.method1 = [](bool enabled){
gClass->method1(enabled);
};
iface.method2 = [](int param1, int param2){
gClass->method2(param1,param2);
};
iface.method3 = [](const char *path, const int& val){
return gClass->method3(path, val);
};
}

Related

Use functions from base class as templates inside derived class

Here is my usecase:
class A:
protected:
virtual void methodA1(const void* const s, const std::streamsize n) const;
inline void methodA2(const void* const s, const std::streamsize n) const;
class B : public A
private:
const char *a;
template <void (*T)(const void* const, const std::streamsize)>
void doOperation(const char* b) {
T(a, b - a);
}
//here comes the template usage
void methodB1(const char *x) {
doOperation<methodA1>(x);
}
void methodB2(const char *x) {
doOperation<methodA2>(x);
}
The problem is that will not compile. I get error like template argument deduction/substitution failed: and invalid use of non-static member function.
How could I achieve the desired behaviour ?
methodA1 is of type void (A::*)(const void* s, std::streamsize) const.
So you have to adjust your code to something like:
class A
{
public:
virtual void methodA1(const void* const s, const std::streamsize n) const = 0;
void methodA2(const void* const s, const std::streamsize n) const {}
};
class B : public A
{
private:
const char *a;
void methodA1(const void* s, std::streamsize n) const override {}
template <void (A::*M)(const void*, std::streamsize) const>
void doOperation(const char* b) {
(this->*M)(a, b - a); // method pointer usage
}
//here comes the template usage
void methodB1(const char *x) {
doOperation<&A::methodA1>(x);
}
void methodB2(const char *x) {
doOperation<&A::methodA2>(x);
}
};

using template classes above main giving error during function call in main

I am using a base class and a child class defined above main in main.cpp
this gives me an error of undefined reference FactoryTraversal::AddPoint::AddPoint(int const&, int const&, int)'
Here is the code:
#include <iostream>
#include <list>
#include <typeinfo>
#include <cmath>
enum traversal_type
{
TRAVERSAL = 0,
TRAVERSALMAX
};
template <class T>
class FactoryTraversal
{
public:
FactoryTraversal();
FactoryTraversal *CreateInstance(const traversal_type &type);
virtual ~FactoryTraversal();
const std::list<int>& GetIndices() const {return indices;}
int GetIndicesSize() const {return indices.size();}
virtual void AddPoint(const T &x, const T &y, int index);
protected:
std::list<int> indices;
};
template<class T>
class Traversal : public FactoryTraversal<T>
{
public:
Traversal();
void AddPoint(const T &x, const T &y, int index);
int GetResultXOR() const {return result_xor;}
private:
T coords_s[2];
T coords_e[2];
int result_xor;
void update_result(int index);
T calculate_distance(const T &x1, const T &x2, const T &y1, const T &y2);
};
template<class T>
Traversal<T>::Traversal():FactoryTraversal<T>()
{
//Do nothing
}
template<class T>
void Traversal<T>::AddPoint(const T &x, const T &y, int index)
{
if (0 == this->GetIndicesSize())
{
this->indices.push_front(index);
coords_s[0] = x; coords_s[1] = y;
coords_e[0] = x; coords_e[1] = y;
}
else
{
T d1 = this->calculate_distance(x,coords_s[0],y,coords_s[1]);
T d2 = this->calculate_distance(x,coords_e[0],y,coords_e[1]);
if (d1 < d2)
{
this->indices.push_front(index);
coords_s[0] = x; coords_s[1] = y;
}
else
{
this->indices.push_back(index);
coords_e[0] = x; coords_e[1] = y;
}
}
this->update_result(index);
}
template<class T>
T Traversal<T>::calculate_distance(const T &x1, const T &x2, const T &y1, const T &y2)
{
if (typeid(T) == typeid(int))
{
return std::min(std::abs(x1-x2),std::abs(y1-y2));
}
return 0;
}
template<class T>
void Traversal<T>::update_result(int index)
{
if (0 == this->GetIndicesSize())
result_xor = index;
else
result_xor ^= index;
}
template<class T>
FactoryTraversal<T>::FactoryTraversal()
{
indices.clear();
}
template<class T>
FactoryTraversal<T>::~FactoryTraversal()
{
//Do Nothing
}
template<class T>
FactoryTraversal<T>* FactoryTraversal<T>::CreateInstance(const traversal_type &type)
{
if (TRAVERSAL == type)
return new Traversal<T>();
else
return NULL;
}
FactoryTraversal<int> factory_traversal;
Traversal<int> *traversal = new Traversal<int>();
int main()
{
int T;
std::cin>>T;
int output[T];
for (int i = 0; i < T; ++i)
{
int N;
std::cin>>N;
FactoryTraversal<int> factory_traversal;
FactoryTraversal<int> *traversal = factory_traversal.CreateInstance(TRAVERSAL);
for (int j = 0; j < N; ++j)
{
int x, y;
std::cin>>x>>y;
traversal->AddPoint(x,y,j+1);
}
Traversal<int> *tmp = dynamic_cast<Traversal<int> *>(traversal);
if (tmp)
output[i] = tmp->GetResultXOR();
else
output[i] = 0;
}
for (int i = 0; i < T; ++i)
{
std::cout<<output[i]<<std::endl;
}
return 0;
}
Interfaces in C++ are called "abstract classes", and classes are abstract if they have at least one "pure virtual function". A function is a pure virtual function if it is prefixed with virtual and has a trailing =0 in its declaration. This is what you want for FactoryTraversal::AddPoint:
virtual void AddPoint(const T &x, const T &y, int index) = 0;
Now the derived class is expected to define it (and it does). Without AddPoint being pure virtual, you are forced to provide an implementation for it in the base class, which you could do simply as:
virtual void AddPoint(const T &x, const T &y, int index){}
This gives a "default" or fallback implementation for when a derived class chooses not to override the method. If it were pure virtual, the derived class is forced to define it, lest a call to it result in a compiler error (otherwise the derived class is also considered abstract).
Note that destructors should never be pure virtual. The way you have it right now is great; you unconsciously followed the rules I've outlined above.
Some other notes:
Variable length arrays are not legal C++, this is a compiler extension:
int output[T]; // T is read from command line
Use a vector instead:
std::vector<int> output(T);
You have memory leaks as-is. Use a managed pointer like unique_ptr so you don't have to worry about new and delete
I stated that you wanted AddPoint to be pure virtual and I mean it. You code won't compile if that's the first step you take, though. It looks like you merged a base class and a factory into one; split those out.
Putting it all together we can define our new base class as:
template<class T>
class TraversalBase
{
public:
virtual ~TraversalBase(){}
const std::list<int>& GetIndices() const {return indices;}
int GetIndicesSize() const {return indices.size();}
virtual void AddPoint(const T &x, const T &y, int index) = 0;
protected:
std::list<int> indices;
};
The derived class becomes (very little change, also notice the override keyword):
template<class T>
class Traversal : public TraversalBase<T>
{
public:
void AddPoint(const T &x, const T &y, int index) override;
int GetResultXOR() const {return result_xor;}
private:
T coords_s[2];
T coords_e[2];
int result_xor;
void update_result(int index);
T calculate_distance(const T &x1, const T &x2, const T &y1, const T &y2);
};
And our Factory class is much simplified:
template <class T>
struct FactoryTraversal
{
FactoryTraversal(){}
std::unique_ptr<TraversalBase<T>> CreateInstance(const traversal_type &type);
~FactoryTraversal(){}
};
Live Demo (C++11)

Mapping functions with variable arguments and calling by string c++

I would like to have some fair idea how to map functions with variable arguments,return type of int and call it by a string..
Just for an example...
int func1(int a, int b);
int func2(int a1, int b1 , int* c1);
int func3(char* dummy);
int func4(double x, long y, int z, char** table);
int func5(double d1, double b1);
int func6(int* p, double* q, int i);
I just need a common function called
int CallFunction("funcname", param1, param2, ...);
for example
CallFunction("func1", 10, 20); /* calling function func1 and return func1 result*/
I know how to map functions using functions pointers having constant arguments but variable arguments seems to be complicated.. could anyone shower some idea how to do it.
I even explored Variadic templates.. But seems to complicated calling functions using strings..
I had exact the same problem.
Solved it with this solution:
#include <iostream>
#include <map>
#include <string>
int func0(int x)
{
std::cout << x << std::endl;
}
int func1(int x, int y)
{
std::cout << (x + y) << std::endl;
}
template <class... Args>
struct MapHolder{
static std::map<std::string, int (*)(Args...)> CallbackMap;
};
template <class... Args>
std::map<std::string, int (*)(Args...)> MapHolder<Args...>::CallbackMap;
class Callback {
public:
template <class ...Args>
void RegisterFunction(std::string name, int (*func)(Args...)) {
MapHolder<Args...>::CallbackMap[name] = func;
}
template <class ...Args>
int ExecuteFunction(std::string name, Args &&... args) {
return MapHolder<Args...>::CallbackMap[name](std::forward<Args>(args)...);
};
};
int main(int argc, char *argv[])
{
Callback cb;
cb.RegisterFunction("func0", &func0);
cb.RegisterFunction("func1", &func1);
cb.ExecuteFunction("func0", 42);
cb.ExecuteFunction("func1", 42, 42);
return 0;
}
This snippet is based on this answer. I only use other class/function names.
I'm not sure if this is what you're looking for, but anyway...
1. Creating a generic value holder
boost.any didn't make it into the standard, and, in case you don't know what it is, it allows you to store any C++ value in a single type (any) and get it back if you know the type. The following is a toy implementation of it:
struct TypeHandler {
void* (*copyFrom)(void *src);
void (*destroy)(void *p);
};
template<typename T>
TypeHandler *thandler() {
struct THandler {
static void *copyFrom(void *p) { return new T(*(T *)p); }
static void destroy(void *p) { delete (T *)p; }
};
static TypeHandler th = { &THandler::copyFrom, &THandler::destroy };
return &th;
}
TypeHandler contains two pointer to functions that know how to copy and how to destroy a specific C++ type. A Value can hold any type because it's composed of a void * and a pointer to a TypeHandler. When copying or destroying is required on the instance it asks to the specific type handler function...
struct Value {
TypeHandler *th;
void *p;
Value(const Value& other) : th(other.th), p(th->copyFrom(other.p)) { }
template<typename T> Value(const T& x) : th(thandler<T>()), p(new T(x)) { }
~Value() { th->destroy(p); }
Value& operator=(const Value& other) {
if (this != &other) {
th->destroy(p);
th = other.th;
p = th->copyFrom(other.p);
}
return *this;
}
template<typename T>
Value& operator=(const T& other) {
th->destroy(p);
th = thandler<T>();
p = new T(other);
return *this;
}
template<typename T>
T& to() const {
if (th != thandler<T>()) throw Error("type mismatch");
return *(T*)p;
}
};
Note that Value is copyable and can be passed by value and can be returned by functions.
Any copyable object is implicitly convertible into a Value and I can also convert it back to the original type with to<T>().
2. Creating the name->function maps
std::map<std::string, Value (*)(const Value&)> map1;
std::map<std::string, Value (*)(const Value&, const Value&)> map2;
Value call(const std::string& name, const Value& x1) {
return map1.at(name)(x1);
}
Value call(const std::string& name, const Value& x1, const Value& x2) {
return map2.at(name)(x1, x2);
}
Here I've created explicit maps for 1 and 2 arguments. May be this can be done using C++11 variadic templates, I didn't try. In C++03 libraries it's common to see this kind of stuff copy-n-pasted up to say n=20 to cover reasonable cases.
3. Macrology
To simplify registration of functions I wrote two ugly macros. May be this can be done also using variadic macros or templates (I'm not so sure about it, especially the automatic registration of the wrapper in the map).
#define regfunc1(name, t1) \
Value name(const Value& x1) { \
return name(x1.to<t1>()); \
} \
struct name##_ { \
name##_() { map1[#name]=&name; } \
} name##_instance
#define regfunc2(name, t1, t2) \
Value name(const Value& x1, const Value& x2) { \
return name(x1.to<t1>(), x2.to<t2>()); \
} \
struct name##_ { \
name##_() { map2[#name]=&name; } \
} name##_instance
4. Use
double square(double x) {
return x*x;
}
double hyp2(double x, double y) {
return x*x+y*y;
}
int mylen(const std::string& s) {
return s.size();
}
regfunc1(square, double);
regfunc2(hyp2, double, double);
regfunc1(mylen, std::string);
int main() {
Value x = 42;
Value y = std::string("This is a test");
Value z = 3.14;
printf("%0.3f\n", call("square", z).to<double>());
printf("%0.3f\n", call("hyp2", z, z).to<double>());
printf("mylen(\"%s\") = %i\n",
y.to<std::string>().c_str(),
call("mylen", y).to<int>());
return 0;
}

Hiding C++ template class behind a common interface

I am pretty new with templates
I have below code that I try to hide my template class behind a base interface class.
It works now but I dont know if its a good way to do what I try to do.
For example is it possible to collect insertItem() functions in one common function also?
struct MyMainClass
{
virtual void writeFirstItem() = 0;
virtual void insertItem(int Key, int Value) = 0;
virtual void insertItem(void* Key, int Value) = 0;
};
template<typename T>
struct MyTempClass : public MyMainClass
{
template<typename T>
struct cmp_str
{
bool operator()(typename T const a, typename T const b) const
{
if(a > b)
return true;
return false;
};
};
template<>
struct cmp_str<wchar_t*>
{
bool operator()(wchar_t* const a, wchar_t* const b) const
{
return std::wcscmp(a, b) < 0;
};
};
template<>
struct cmp_str<char*>
{
bool operator()(char* const a, char* const b) const
{
return std::strcmp(a, b) < 0;
};
};
typedef std::map<typename T, int, cmp_str<typename T> > Mymap;
typedef typename Mymap::const_iterator mymapit;
typename Mymap mymap;
template<typename T>
void insert(T keyVal, int myvalue)
{
mymap[keyVal] = myvalue;
};
void writeFirstItem()
{
std::wcout << std::wstring(L"(") << mymap.begin()->first << L"," << mymap.begin()->second << L")" << std::endl;
}
void insertItem(void* Key, int Value)
{
insert((T)Key, Value);
}
//this one shouldnt be called
void insertItem(int Key, int Value){}
};
template<> template<>
void MyTempClass<int>::insert<int>(int keyVal, int myvalue)
{
mymap[keyVal] = myvalue;
}
template<>
void MyTempClass<int>::insertItem(int Key, int Value)
{
insert(Key, Value);
}
int wmain(int argc, wchar_t* argv[])
{
MyMainClass* a;
MyMainClass* b;
MyMainClass* c;
wchar_t a1[6] = L"asdf";
wchar_t a2[6] = L"12345";
wchar_t a3[6] = L"xyzs";
wchar_t a4[6] = L"12345";
int b1 = 3;
int b2 = 5;
int b3 = 88;
int b4 = 3;
char c1[6] = "casdf";
char c2[6] = "c1234";
char c3[6] = "cxyzs";
char c4[6] = "c1234";
a = new MyTempClass<wchar_t*>;
a->insertItem(a1,3);
a->insertItem(a2,5);
a->insertItem(a3,9);
a->insertItem(a4,3);
b = new MyTempClass<int>;
b->insertItem(b1, 4);
c = new MyTempClass<char*>;
c->insertItem(c1,77);
c->insertItem(c3,99);
a->writeFirstItem();
b->writeFirstItem();
c->writeFirstItem();
}
What you've got is type redefinition, I guess. This is because when you're compiling without "else" section, only one cmp_str specialization is actually "instantiated", when you uncomment "else" - another "struct cmp_str" appears in the same translation unit.
Please tell us what you're trying to achieve with this combination.
The problem is that your first argument to insert() is of incorrect type.
When you instantiate MyTempClass<int>, the insert() function's signature becomes:
void insert(int keyVal, int myvalue); however your call-site for insert looks like, b->insert(a1, 3); where a1 is not of type int.

Cannot convert 'this' pointer to Class&

Can someone tell why i'm getting this error when compling this class?
class C
{
public:
void func(const C &obj)
{
//body
}
private:
int x;
};
void func2(const C &obj)
{
obj.func(obj);
}
int main() { /*no code here yet*/}
The C::func() method doesn't promise that it won't modify the object, it only promises that it won't modify its argument. Fix:
void func(const C &obj) const
{
// don't change any this members or the compiler complains
}
Or make it a static function. Which sure sounds like it should be when it takes a C object as an argument.
You need to mark C::func(const C &obj) as const as you're calling it from a const object. The correct signature would look like this:
void func(const C& obj) const
The problem is that in func2() you're calling a non-const function (C::func()) using a const object.
Change the signature of C::func() to:
void func(const C &obj) const
{
// whatever...
}
so that it can be called with const objects.
Because:
this
is a const pointer to current obj.
Therefore you can either make the func to be const:
class C
{
public:
void func(const C &obj) const
{
//body
}
private:
int x;
};
void func2(const C &obj)
{
obj.func(obj);
}
int main() {
return 0;
}
OR
you can remove the constness of the this pointer like this:
class C
{
public:
void func(const C &obj)
{
//body
}
private:
int x;
};
void func2(const C &obj)
{
(const_cast<C &>(obj)).func(obj);
}
int main() {
return 0;
}
Hope that helps.