Templating function pointers using Maps - c++

I am trying to use templates to create a mapping for understanding the concepts, but I am getting an error and failed to understand what I am doing wrong.
Can anyone take a look and let me know what I am doing wrong ? Please share a working example of a design if possible which I would really appreciate.
Thanks
#include <iostream>
#include <map>
using namespace std;
enum MathOperations
{
ADD = 0,
SUBTRACT,
MULTIPLY,
DIVISION
};
template <typename T>
T Addition(T a, T b)
{
return a + b;
}
template <typename T>
T Subtraction(T a, T b)
{
return a - b;
}
template <typename T>
struct MathOp
{
typedef T (*FuncPtr) (T, T);
};
/* I am getting a warning here, which says variable templates are c++1 extension */
template <typename T>
const std::map<MathOperations, typename MathOp<T>::FuncPtr> MathMap = {
{ MathOperations::ADD, &Addition<T> },
{ MathOperations::SUBTRACT, &Subtraction<T> }
};
int main ()
{
MathOp<int> mathIntObj;
/* I am getting error here */
/* No viable overloaded operator[] for type 'const std::map<MathOperations, typename MathOp<int>::FuncPtr>' */
std::cout << *(MathMap<int>[MathOperations::ADD])(1, 2) << endl;
return 0;
}
EDIT:
Thanks to #Piotr Skotnicki, who shared a solution for my error.
I had to make following changes:
std::cout << (*MathMap<int>.at(MathOperations::ADD))(1, 2) << endl;
Removed
MathOp<int> mathIntObj;
Still, I need to fix the warning. Any ideas ? Thanks

Why not use lambdas and the class template std::function, thus greatly reducing your code size:
#include <iostream>
#include <map>
#include <functional>
using namespace std;
enum MathOperations
{
ADD = 0,
SUBSTRACT,
MULTIPLY,
DIVISION
};
template <typename T>
const std::map<MathOperations, typename std::function<T(T,T)>> MathMap = {
{ MathOperations::ADD, [](T a, T b){ return a + b; } },
{ MathOperations::SUBSTRACT, [](T a, T b) { return a - b; } }
};
int main ()
{
std::cout << (MathMap<int>.at(MathOperations::ADD))(3, 2) << endl;
std::cout << (MathMap<int>.at(MathOperations::SUBSTRACT))(6, 5) << endl;
return 0;
}

Related

std::function & std::forward with variadic templates

Recently I was reading about variadic templates and based on an example I've seen online I was trying to implement a basic event-system. So far it seems to work fine but I was trying to go a step further and allow N number of arguments to be passed to an event handler function / callback, unfortunately the build error I'm getting is the following and I'm not sure what I'm doing wrong. I looked into similar source codes but still cant figure out what's the issue.
D:\Development\lab\c-cpp\EventEmitter3\src\main.cpp:30:68: error: parameter packs not expanded with '...':
return std::any_cast<std::function<R(Args)>>(eventCallback)(std::forward<Args>(args)...);
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
D:\Development\lab\c-cpp\EventEmitter3\src\main.cpp:30:68: note: 'Args'
Build finished with error(s).
Here is what I have so far, if you remove the ... the event system works fine for the 2 registered events in main.
#include <any>
#include <string>
#include <iostream>
#include <functional>
#include <unordered_map>
class EventEmitter
{
private:
std::unordered_map<std::string, std::any> events;
public:
EventEmitter() {}
void on(const std::string &eventName, const std::any &eventCallback)
{
events[eventName] = eventCallback;
}
template <typename R>
R emit(const std::string &eventName)
{
const std::any &eventCallback = events[eventName];
return std::any_cast<std::function<R(void)>>(eventCallback)();
}
template <typename R, typename... Args>
R emit(const std::string &eventName, Args &&...args)
{
const std::any &eventCallback = events[eventName];
return std::any_cast<std::function<R(Args)>>(eventCallback)(std::forward<Args>(args)...);
}
virtual ~EventEmitter() {}
};
int fun1()
{
std::cout << "fun1" << std::endl;
return 1;
}
double fun2(int i)
{
std::cout << "fun2" << std::endl;
return double(i);
}
double fun3(int x, int y)
{
std::cout << "fun3" << std::endl;
return double(x + y);
}
int main(int argc, char *argv[])
{
EventEmitter e;
e.on("fun1", std::function<int(void)>(fun1));
e.on("fun2", std::function<double(int)>(fun2));
e.emit<int>("fun1");
e.emit<double, int>("fun2", 1);
// Variadic would have been handy right here I guess?
// e.on("fun3", std::function<double(int, int)>(fun3));
// e.emit<double, int>("fun3", 1, 2);
return 0;
}
How can I fix this?
Well, you need to expand it.
return std::any_cast<std::function<R(Args...)>>(eventCallback)(std::forward<Args>(args)...);
^^^^^^^

Practice with templates returning error

The code is working in that it couts haha but it causes an error because it says:
Process returned -1073741819 <0xC0000005>
And a window pops up telling me if I would like to send an error message. Why is this?
#include <iostream>
using namespace std;
template <class A>
A print( A a ) {
cout << a;
}
template <class T>
class David {
T a;
public:
David( T something ) : a( something ) {}
void laugh() {
print(a);
}
};
int main() {
David <string> Do("Hahaha");
Do.laugh();
}
template <class A>
A print( A a ) {
cout << a;
}
It`s incorrect. No return value in function, so, compiler returns some garbage from stack.
And better i think will be this declaration
template<class A>
void print(const A& a) { cout << a; }

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.

Using boost::mpl, how can I get how many template classes are not "Empty", and call some macro with this number?

I want to call a macro with some arguments depending on the result of boost::mpl::eval_if (or a similar function) that could give how many template arguments are not empty. Say we have some pseudocode like the following:
struct EmptyType { };
template<class arg1=EmptyType, class arg2=EmptyType, class arg3=EmptyType>
class my_class
{
eval_if<is_not_same<arg1, EmptyType>, FILL_MY_CLASS_DEFINE(1)> else
eval_if<is_not_same<arg2, EmptyType>, FILL_MY_CLASS_DEFINE(2)> else
eval_if<is_not_same<arg3, EmptyType>, FILL_MY_CLASS_DEFINE(3)>;
};
I am trying to fill my class with some content depending on how many arguments are EmptyType. I wonder how such thing can be done in C++03 via Boost.MPL/Preprocessor or some other Boost library?
You don't need preprocessor or mpl. Partial specialization is you need:
Edit This works in C++03, see it live: https://ideone.com/6MaHJ
#include <iostream>
#include <string>
struct EmptyType { };
template<class arg1=EmptyType, class arg2=EmptyType, class arg3=EmptyType>
class my_class
{
// FILL_MY_CLASS_DEFINE(3)
};
template<class arg1, class arg2>
class my_class<arg1,arg2,EmptyType>
{
// FILL_MY_CLASS_DEFINE(2)
};
template<class arg1>
class my_class<arg1,EmptyType,EmptyType>
{
// FILL_MY_CLASS_DEFINE(1)
};
template<>
class my_class<EmptyType,EmptyType,EmptyType>
{
// FILL_MY_CLASS_DEFINE(0)
};
int main(int argc, const char *argv[])
{
my_class<std::string, double, int> a;
my_class<std::string, int> b;
my_class<void> c;
return 0;
}
Are you looking for variadic templates?
#include <tuple>
#include <iostream>
#include <string>
template <typename... Arg>
struct my_class
{
// getting the size of the argument list:
enum { size = sizeof...(Arg) }; // in absense of static fields with initializers...
// demo filling the struct with data:
std::tuple<Arg...> arg_data;
my_class(Arg&&... a) : arg_data(std::forward<Arg>(a)...) { }
};
int main(int argc, const char *argv[])
{
my_class<std::string, int> a("hello world", 42);
std::cout << "size: " << a.size << std::endl;
std::cout << "last: " << std::get<a.size-1>(a.arg_data) << std::endl;
return 0;
}
Output:
size: 2
last: 42
When you have many template arguments, a partial specialization can be impractical and error-prone.
The code below will do what you want, but as it was already mentioned in other answers, it's not always the best way to proceed.
#include <boost/mpl/count_if.hpp>
#include <boost/mpl/not.hpp>
#include <boost/type_traits/is_same.hpp>
using boost::is_same;
using boost::mpl::_;
using boost::mpl::not_;
using boost::mpl::count_if;
#define FILL_MY_CLASS_DEFINE(x) static const int __x__ = x // an example, watch out: no semicolon at the end
struct EmptyType { };
template<class arg1=EmptyType, class arg2=EmptyType, class arg3=EmptyType>
class my_class
{
// count the types which are not equal to EmptyType
static const long NonEmptyCount = count_if<type, not_<is_same<_, EmptyType> > >::value;
// invoke a macro with an argument
FILL_MY_CLASS_DEFINE(NonEmptyCount);
};

How to call generic template function in a specialization version

Have a problem about how to call the generic template version in a specialization version.
Here is the sample code. But the "vector::push_back(a)" calls itself recursively.
#include <iostream>
#include <vector>
using namespace std;
namespace std
{
template<>
void vector<int>::push_back(const int &a)
{
cout << "in push_back: " << a << endl;
vector::push_back(a); // Want to call generic version
}
}
int main()
{
vector<int> v;
v.push_back(10);
v.push_back(1);
return 0;
}
When you create specialization for some template (no difference class of function), you tell to compiler to generate that one instead of general. So in fact if you have specialization you have no general version for that specialization and you can't call it, because it doesn't exists.
You can simply extract the code into another template function:
template<typename T>
void baseF(T t) { ... }
template<typename T>
void F(T t) { baseF<T>(t); }
template<>
void F<int>(int t) { baseF<int>(t); }
Well, to complement, I think it works for template function specification in some situations.
#include <iostream>
#include <vector>
using namespace std;
class Base
{
public:
virtual int test() {return 0;}
};
class Derived : public Base
{
public:
virtual int test() {return 1;}
};
template<class T>
void TestOutput(T* a)
{
cout << a->test() << endl;
}
template<>
void TestOutput(Derived* a)
{
cout << "something else" << endl;
TestOutput<Base>(a);
}
int main()
{
Derived d;
TestOutput(&d);
}
I compiled it with visual studio 2013 and the output is:
something else
1
Although I don't think you can always find a TestOutput function of Base to call the generic one.