I want to retreive data from a source, made available through one function, by a set of different functions. I come from c, so I have this example:
#include <iostream>
using namespace std;
void getInt(void *v, const double &src) {*static_cast<int*>(v) = src; }
void getDouble(void *v, const double &src) {*static_cast<double*>(v) = src; }
struct twoInt{int a; int b;};
void getTwoInt(void *v, const double &src)
{
static_cast<twoInt*>(v)->a = src;
static_cast<twoInt*>(v)->b = static_cast<int>(src*10) % 10;
}
template <typename T>
void getData(T f, void* val)
{
double dataSource = 2.1;
f(val, dataSource);
}
int main()
{
int valI;
double valD;
twoInt valTwoInt;
getData(getInt, static_cast<void*>(&valI));
cout << "Int: " << valI << endl;
getData(getDouble, static_cast<void*>(&valD));
cout << "Double: " << valD << endl;
getData(getTwoInt, static_cast<void*>(&valTwoInt));
cout << "Int1: " << valTwoInt.a << ", Int2: " << valTwoInt.b <<endl;
}
But I would like to do it in a modern C++ way, and without the void pointers, to have more type safety.
You don't need type erasure here, so correct type and template do the job:
void getInt(int& out, double src) { out = src; }
void getDouble(double& out, double src) { out = src; }
struct twoInt{int a; int b;};
void getTwoInt(twoInt& v, double src)
{
v.a = src;
v.b = static_cast<int>(src * 10) % 10;
}
template <typename F, typename T>
void getData(F f, T& val)
{
double dataSource = 2.1;
f(val, dataSource);
}
int main()
{
int valI;
getData(getInt, valI);
std::cout << "Int: " << valI << std::endl;
double valD;
getData(getDouble, valD);
std::cout << "Double: " << valD << std::endl;
twoInt valTwoInt;
getData(getTwoInt, valTwoInt);
std::cout << "Int1: " << valTwoInt.a << ", Int2: " << valTwoInt.b <<std::endl;
}