Reputation: 485
the question may look silly ,but i want to ask.. Is there any way we can declare a method in a class with same signature but different return type (like int fun(int) and float fun(int) ) and during the object creation can we dynamically decide which function to be executed! i have got the compilation error...is there any other way to achieve this logic may be using templates...
Upvotes: 4
Views: 837
Reputation: 39109
You can (but shouldn't*) use a proxy class that overloads the conversion operators.
Let me take my example from Dot & Cross Product Notation:
[...]
There is also the possibility of having operator* for both dot-product and cross-product.
Assume a basic vector-type (just for demonstration):
struct Vector {
float x,y,z;
Vector() {}
Vector (float x, float y, float z) : x(x), y(y), z(z) {}
};
We observe that the dot-product is a scalar, the cross-product is a vector. In C++, we may overload conversion operators:
struct VecMulRet {
public:
operator Vector () const {
return Vector (
lhs.y*rhs.z - lhs.z*rhs.y,
lhs.z*rhs.x - lhs.x*rhs.z,
lhs.x*rhs.y - lhs.y*rhs.x
);
}
operator float () const {
return lhs.x*rhs.x + lhs.y*rhs.y + lhs.z*rhs.z;
}
private:
// make construction private and only allow operator* to create an instance
Vector const lhs, rhs;
VecMulRet (Vector const &lhs, Vector const &rhs)
: lhs(lhs), rhs(rhs)
{}
friend VecMulRet operator * (Vector const &lhs, Vector const &rhs);
};
Only operator* is allowed to use struct VecMulRet, copying of VecMulRet is forbidden (paranoia first).
Operator* is now defined as follows:
VecMulRet operator * (Vector const &lhs, Vector const &rhs) {
return VecMulRet (lhs, rhs);
}
Et voila, we can write:
int main () {
Vector a,b;
float dot = a*b;
Vector cross = a*b;
}
Btw, this is blessed by the Holy Standard as established in 1999.
If you read further in that thread, you'll find a benchmark that confirms that this comes at no performance penalty.
If that was too much to grasp, a more constructed example:
struct my_multi_ret {
operator unsigned int() const { return 0xdeadbeef; }
operator float() const { return 42.f; }
};
my_multi_ret multi () {
return my_multi_ret();
}
#include <iostream>
#include <iomanip>
int main () {
unsigned int i = multi();
float f = multi();
std::cout << std::hex << i << ", " << f << std::endl;
}
* You can, but shouldn't, because it does not conform to the principle of least surprise as it is not common practice. Still, it is funny.
Upvotes: 0
Reputation: 300099
@DeadMG proposed the template based solution, however you can simply "tweak" the signature (which is, arguably, what the template argument does).
The idea is simply to add a dummy argument:
struct Foo
{
float fun(float); // no name, it's a dummy
int fun(int); // no name, it's a dummy
};
Then for execution:
int main() {
Foo foo;
std::cout << foo.fun(int()) << ", " << foo.fun(float());
}
This can be used exactly as the template solution (ie invoked from a template method), but is much easier to pull:
I prefer to avoid function template specialization, in general, as with specialization on arguments, the rules for selecting the right overload/specialization are tricky.
Upvotes: 0
Reputation: 146988
You can always take the return value as a template.
template<typename T> T fun(int);
template<> float fun<float>(int);
template<> int fun<int>(int);
Can you decide dynamically at run-time which to call? No.
Upvotes: 7