C++ Creating function map using templates and inheritance - c++

I am trying to create a generic function map using templates.The idea is to inherit from this generic templated class with a specific function pointer type. I can register a function in the global workspace, but I'd rather collect all the functions together in the derived class and register these in the constructor. I think I am almost here but I get a compile error. Here is a stripped down version of my code:
#include <iostream>
#include <string>
#include <map>
#include <cassert>
using namespace std;
int f(int x) { return 2 * x; }
int g(int x) { return -3 * x; }
typedef int (*F)(int);
// function factory
template <typename T>
class FunctionMap {
public:
void registerFunction(string name, T fp) {
FunMap[name] = fp;
}
T getFunction(string name) {
assert(FunMap.find(name) != FunMap.end());
return FunMap[name];
}
private:
map<string, T> FunMap;
};
// specific to integer functions
class IntFunctionMap : public FunctionMap<F> {
public:
int f2(int x) { return 2 * x; }
int g2(int x) { return -3 * x; }
IntFunctionMap() {
registerFunction("f", f); // This works
registerFunction("f2", f2); // This does not
}
};
int main()
{
FunctionMap<F> fmap; // using the base template class directly works
fmap.registerFunction("f", f);
F fun = fmap.getFunction("f");
cout << fun(10) << endl;
return 0;
}
The error I get is:
templatefunctions.cpp: In constructor ‘IntFunctionMap::IntFunctionMap()’:
templatefunctions.cpp:33: error: no matching function for call to ‘IntFunctionMap::registerFunction(const char [3], <unresolved overloaded function type>)’
templatefunctions.cpp:15: note: candidates are: void FunctionMap<T>::registerFunction(std::string, T) [with T = int (*)(int)]

Juan's answer is correct: member functions have an implicit first parameter, which is a pointer to the type of which they are a member. The reason your code fails to compile is that your map supports function pointers with type int (*)(int), but the type of f2 is int (IntFunctionMap::*)(int).
In the specific case that you show here, you can use std::function, which implements types erasure, to present free functions and member functions as the same type. Then you could do what you are trying to do. Note: this requires C++11.
#include <iostream>
#include <string>
#include <map>
#include <cassert>
#include <function>
#include <bind>
using namespace std;
int f(int x) { return 2 * x; }
int g(int x) { return -3 * x; }
typedef std::function<int (int)> F;
// function factory
template <typename T>
class FunctionMap {
public:
void registerFunction(string name, T fp) {
FunMap[name] = fp;
}
T getFunction(string name) {
assert(FunMap.find(name) != FunMap.end());
return FunMap[name];
}
private:
map<string, T> FunMap;
};
// specific to integer functions
class IntFunctionMap : public FunctionMap<F> {
public:
int f2(int x) { return 2 * x; }
int g2(int x) { return -3 * x; }
IntFunctionMap() {
registerFunction("f", f); // This works
registerFunction("f2", std::bind(&f2, this, _1)); // This should work, too!
}
};
int main()
{
FunctionMap<F> fmap; // using the base template class directly works
fmap.registerFunction("f", f);
F fun = fmap.getFunction("f");
cout << fun(10) << endl;
return 0;
}

Related

Using functions in a namespace that hasn't been declared from template

The following code give me an error that 'print2' is not a member of 'N' when using both clang and gcc:
#include <stdio.h>
struct Printer
{
template<class T>
void print(T t)
{
N::print2(*this, t);
}
};
namespace N
{
void print2(Printer& p, int v)
{
printf("%d\n", v);
}
}
int main()
{
Printer p;
p.print(1);
}
If I remove the namespace N and make the print2 function global it works. Why is the lookup different when the function is put in a namespace and when it's not? Unfortunately I can't move the print2 function before struct Printer, which would've been the obvious solution.
Here I am simply declaring the function before Printer, while defining the logic of the function afterwards.
#include <stdio.h>
namespace N {
void print2(int);
}
struct Printer
{
template<class T>
void print(T t)
{
N::print2(t);
}
};
namespace N
{
void print2(int v)
{
printf("%d\n", v);
}
}
int main()
{
Printer p;
p.print(1);
}

How to use std::function as a template

I am new to the std::function concept.
I need to use std::function in following way
I have a class as follows
class A(string ,bool, string, std::function<void()>)
here the std::function<void()> should take different parameters from different objects.
The parameters will be basically different types of enumerations
for example
1)A a(string ,bool, string, std::function<void(enum xyz)>)
2)A b(string ,bool, string, std::function<void(enum abc)>)
3)A c(string ,bool, string, std::function<void(enum efg)>)
I want to know how should i structure the std::function in class A so that i can pass different enumerations as parameter to the class A objects
You can pass a template type as the std::function parameter. Here's an example:
#include <iostream>
#include <functional>
#include <string>
template <class T>
class Foo
{
public:
Foo(std::function<void(T)> f) : f_{f} {}
void call(T in) { f_(in); }
private:
std::function<void(T)> f_;
};
int main()
{
Foo<double> fd{[] (double d) { std::cout << d << '\n'; }};
fd.call(34.2);
Foo<std::string> fs{[] (std::string s) { std::cout << s << '\n'; }};
fs.call("Test!");
return 0;
}
Output:
34.2
Test!
After looking at your question, this is how you need to use the function.
#include <iostream>
#include <string>
#include <functional> //Need to include for std::function use
using namespace std;
//Declare the ENUM here.
enum ePat {xyz=1,abc,efg,mno};
enum ePat_second {def=1,ghi,jkl,opq};
//utility function you want to pass to std function
template <typename T>
void print(T e)
{
}
template <typename T>
class A
{
public:
//Constructore with std function as one of the argument
A(string ,bool , string, std::function<void(T)>)
{
}
};
int main()
{
//Declare your std function types.
std::function<void(ePat)> xyz_display = print<ePat>;
std::function<void(ePat_second)> def_display = print<ePat_second>;
//Pass it to the object.
A<ePat> a("abc" ,true, "abc",xyz_display);
A<ePat_second> b("def" ,true, "def",def_display);
}

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++ : unresolved overloaded function when using function pointers

#include <iostream>
using namespace std;
class B
{
public:
int getMsg(int i)
{
return i + 1;
}
};
class A
{
B b;
public:
void run()
{
taunt(b.getMsg);
}
void taunt(int (*msg)(int))
{
cout << (*msg)(1) << endl;
}
};
int main()
{
A a;
a.run();
}
The above code has a class B inside a class A, and class A has a method taunt that takes a function as an argument. class B's getMsg is passed into taunt...The above code generated the following error message: "error: no matching function for call to 'A::taunt()'"
What's causing the error message in the above code? Am I missing something?
Update:
#include <iostream>
using namespace std;
class B
{
public:
int getMsg(int i)
{
return i + 1;
}
};
class A
{
B b;
public:
void run()
{
taunt(b.getMsg);
}
void taunt(int (B::*msg)(int))
{
cout << (*msg)(1) << endl;
}
};
int main()
{
A a;
a.run();
}
t.cpp: In member function 'void A::run()':
Line 19: error: no matching function for call to 'A::taunt()'
compilation terminated due to -Wfatal-errors.
I'm still getting the same error after changing (*msg)(int) to (B::*msg)(int)
b.getMsg is not the correct way to form a pointer to member, you need &B::getMsg.
(*msg)(1) is not the correct way to call a function through a pointer to member you need to specify an object to call the function on, e.g. (using a temporary) (B().*msg)(1).
The right way to do such things in OOP is to use interfaces so all you need to do is to define an interface and implement it in B class after that pass the pointer of instance which implements this interface to your method in class A.
class IB{
public:
virtual void doSomething()=0;
};
class B: public IB{
public:
virtual void doSomething(){...}
};
class A{
public:
void doSomethingWithB(IB* b){b->doSomething();}
};
This works in VS 2010. The output is the same on all lines:
#include <iostream>
#include <memory>
#include <functional>
using namespace std;
using namespace std::placeholders;
class A
{
public:
int foo(int a, float b)
{
return int(a*b);
}
};
int main(int argc, char* argv[])
{
A temp;
int x = 5;
float y = 3.5;
auto a = std::mem_fn(&A::foo);
cout << a(&temp, x, y) << endl;
auto b = std::bind(a, &temp, x, y);
cout << b() << endl;
auto c = std::bind(std::mem_fn(&A::foo), &temp, _1, y);
cout << c(5) << endl;
}
Basically, you use std::mem_fn to get your callable object for the member function, and then std::bind if you want to bind additional parameters, including the object pointer itself. I'm pretty sure there's a way to use std::ref to encapsulate a reference to the object too if you'd prefer that. I also included the _1 forwarding marker just for another way to specify some parameters in the bind, but not others. You could even specify everything BUT the class instance if you wanted the same parameters to everything but have it work on different objects. Up to you.
If you'd rather use boost::bind it recognizes member functions and you can just put it all on one line a bit to be a bit shorter: auto e = boost::bind(&A::foo, &temp, x, y) but obviously it's not much more to use completely std C++11 calls either.

How to have a c++ object with a method that takes argument the enclosing class?

I am trying to figure out if there's any known pattern/idiom in c++ for what I am trying to do here. Class A must be composed of an object that has a function whose argument must also be of type A. The following code doesn't compile since typeid may not be used in a constant expression. Any suggestions?
#include <iostream>
#include <typeinfo>
using namespace std;
template <typename T>
struct B {
int f(T& i) { cout << "Hello\n"; }
};
class A {
B<typeid(A)> b;
};
int main()
{
A k;
}
Your stated requirements don't need templates at all, just a forward declaration:
#include <iostream>
class A; // forward declare A
struct B {
int f(A &i); // declaration only, definition needs the complete type of A
};
class A {
B b;
};
int B::f(A &i) { std::cout << "Hello\n"; } // define f()
int main()
{
A k;
}
You are looking for B<A> b; The following program compiles without error or warning on g++ 4.4.3.
#include <iostream>
#include <typeinfo>
using namespace std;
template <typename T>
struct B {
int f(T& i) { cout << "Hello\n"; return 0; }
};
class A {
public:
B<A> b;
};
int main()
{
A k;
return k.b.f(k);
}
Note: If you are using templates only to avoid forward declaration, my solution is wrong. But, I'll leave it here in case you are using templates for some other legitimate reason.