CAUTION!

CAUTION! DANGER ZONE ahead. Beware of misinformation on the open internet. Contents of the site are mere opinions and are not always facts!

Saturday, October 25, 2014

Overloading functions with same signatures

The static polymorphism in C++ allows multiple functions with the same name offer different functionalities via function overloading. The overloaded functions vary in their signature and the compiler would resolve the function calls based on the parameters passed to the function. It is not possible to overload functions with same parameters. Sometimes, it is desirable to overload functions based only on the return type. One such scenario is shown below, where the data needs to be de-serialized into C++ POD types. The functions with same name and signature cause ambiguity in calling.

int get(Json::Value);
std::string get(Json::Value);

And thus the functions should either be renamed or emulate overloading. The disadvantage of renaming the functions to distinct names is that they cannot be called from other template functions or additional mechanism should be implemented by the template functions to determine the template parameter type and then call the suitable function.

int getInt(Json::Value);
std::string getString(Json::Value);

template<typename T>
struct POD
{
    T value;
    Json::Value operator=(Json::Value v)
    {
         value = ; //determine the type of T and call the suitable function for assignment 
         return v;
    }
};

Taking advantage of the type casting, it can be achieved by overloading the conversion/ type-cast operators. The casting can be either implicit or explicit.

struct Conv
{
    Json::Value val;

    Conv(Json::Value v) :val(v) { }
    operator std::string() { /*Convert and Return*/}
    operator int() { /*Convert and Return*/ }
};

int x = Conv(jsonVal); // create an anonymous object and convert

The overloading can also be achieved by template specialization and calling the required function explicitly.

namespace Conv
{
    template<typename T>
    T get(Json::Value); // linker complains for types not specialised
    template<>
    int get(Json::Value v)
    {
        /* Convert and Return*/
    }

    template<>
    std::string get(Json::Value v)
    {
        /* Convert and Return*/
    }
}

template<typename T>
struct POD
{
    T value;

    Json::Value operator=(Json::Value v)
    {
         value = Conv::get<T>(v);
         return v;
    }
};