srinuvenu
srinuvenu

Reputation: 485

Can we declare a function with the same signature but different return type in the base class?

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

Answers (3)

Sebastian Mach
Sebastian Mach

Reputation: 39109

You can (but shouldn't*) use a proxy class that overloads the conversion operators.

Long example with actual usecase *

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.

Short example for demonstration *

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

Matthieu M.
Matthieu M.

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:

  • less wordy
  • function template specialization should be defined outside the class (although VC++ will accept inline definition in the class)

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

Puppy
Puppy

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

Related Questions