I have a class with a member data which is a pointer to a double function:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
//.h file
class A
{
protected:
double (*ptrToFucntion)( double );
public:
void SetFunction( string fName );
};
//.cpp file
void A::SetFunction( string fName )
{
//depending on fName choose function
ptrToFunction = &function;
}
But what if the return type of a function can differ from double. How to declare ptrToFunction then. I suspect that I should use a template but do not know exactly how.
NOTE: I do not want to variate the argument type. Only the return type.
For example, I want to do something like this:
1 2 3 4 5 6 7 8 9 10
inlineint Floor( double x ) { return floor( x ); }
inlinefloat Sin( double x ) { return sin( x ); }
inlinedouble Exp( double x ) { return exp( x ); }
...
A a, b, c;
a.SetFunction( "Floor" );
b.SetFunction( "Sin" );
c.SetFunction( "Exp" );
// But what if the return type of a function can differ from double. How to
// declare ptrToFunction then. I suspect that I should use a template but do
// not know exactly how.
// NOTE: I do not want to variate the argument type. Only the return type.
#include <cmath>
#include <iostream>
#include <string>
class A {
protected:
int myfloor (double val) { returnstatic_cast<int>(std::floor(val)); }
float mysin (double val) { return std::sin(val); }
double myexp(double val) { return std::exp(val); }
enumclass Tag { RINT, RFLOAT, RDOUBLE };
Tag rtype;
union Horror {
int myint;
float myfloat;
double mydouble;
};
Horror horror {};
public:
void setFunction(std::string name)
{
if(name == "Floor") {
rtype = Tag::RINT;
return;
}
if(name == "Sin") {
rtype = Tag::RFLOAT;
return;
}
if(name == "Exp") {
rtype = Tag::RDOUBLE;
return;
}
std::cout << "\nWhat are you talking about, dude? I don't know "
<< name << ".\n";
}
A& operator()(double val) {
switch(rtype) {
case Tag::RINT:
horror.myint = myfloor(val);
break;
case Tag::RFLOAT:
horror.myfloat = mysin(val);
break;
case Tag::RDOUBLE:
horror.mydouble = myexp(val);
break;
}
return *this;
}
friend std::ostream& operator<<(std::ostream& os, const A& a)
{
switch(a.rtype) {
case Tag::RINT:
os << a.horror.myint;
break;
case Tag::RFLOAT:
os << a.horror.myfloat;
break;
case Tag::RDOUBLE:
os << a.horror.mydouble;
break;
}
return os;
}
};
void waitForEnter();
int main()
{
A a;
a.setFunction("Floor");
A b;
b.setFunction("Sin");
A c;
c.setFunction("Exp");
std::cout << "a(5.5): " << a(5.5) << '\n';
std::cout << "b(5.5): " << b(5.5) << '\n';
std::cout << "c(5.5): " << c(5.5) << '\n';
waitForEnter();
return 0;
}
void waitForEnter()
{
std::cout << "\nPress ENTER to continue...\n";
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
}
By the way if I cannot specialize on return types, what do I do here when write:
1 2 3 4 5
template<typename T>
inline T Mimic( T x )
{
return x;
}
And it works in this way well: ptrToFunction = &Mimic<double>;
I think the compiler can still recognise the correct function by the argument types, not the return value. Does
1 2 3
template<typename T>
T Mimic(int x) { return “something which is a T”; }
ptrToFunction = &Mimic<double>;
The problem runs deeper than that: you are basically asking the compiler to do magic What-Am-I? conversions with your data. You might as well throw out the type system.
On top of that, you are trying to create a pointer to a function without letting the compiler know anything about the function. How exactly is the compiler supposed to call that function? Again, you're asking for magic metadata bloat that the runtime has no need to know.
Return a double, and let the caller decide what to do with it.