BrainStone
BrainStone

Reputation: 3205

Function with multiple types for same parameter

So I have come across a problem where I have a function with multiple parameters. Out of usability I started overloading it so that for instace I can pass a std::string instead of a std::fstream instance. In this overload a new std::fsteam will be constructed from that string and then the other function will be called. Like this:

void func(const std::string & filename) {
  std::fstream file(filename);

  func(file)
}

void func(std::fstream & file) {
  // ...
}

This all works fine. But when you start doing this for more than one parameter or more than 2 possible types everything starts becoming a mess and you might have to write lots of overloads with duplicate code etc.
So I was wondering if there was a more elegant solution to this problem for as many parameters as you need.

I know this problem is not specific to C++ but I'm interested in solutions for the problem in C++.

Upvotes: 1

Views: 863

Answers (2)

BrainStone
BrainStone

Reputation: 3205

So I found a pretty decent and expandable solution:

Let's assume we have a function that accepts 3 paramters of the type type_right1, type_right2 and type_right3 but we also want to provide it with the additional overloads for the respective types type_right1, type_wrong2 and type_wrong3. We also asume to get from type_wrongX to type_rightX we just call the constructor of the latter and pass the former. The code looks like this:

template<class T1, class T2>
void func(type_wrong1 arg1, T1 arg2, T2 arg3) {
  func(type_right1(arg1), arg2, arg3);
}

template<class T1>
void func(type_right1 arg1, type_wrong2 arg2, T1 arg3) {
  func(arg1, type_right2(arg2), arg3);
}

void func(type_right1 arg1, type_right2 arg2, type_wrong3 arg3) {
  func(arg1, arg2, type_right2(arg3));
}

void func(type_right1 arg1, type_right2 arg2, type_right3 arg3) {
  // actual function
}

This solution can be easily expanded with both more parameters and more than two types per parameter and requires a lot less writing and also just generates the functions you actually need!
Thank you for your help.

Upvotes: 1

Sam Varshavchik
Sam Varshavchik

Reputation: 118435

One possible solution is to use helper classes:

class param1 {

public:
    param1(const std::string & filename)
          : filename(filename), file(nullptr)
    {
    }

    param1(std::fstream &file) : file(&file)
    {
    }

    std::string filename;
    std::fstream *file;
};

class param2 {

public:
    param2(int flag);
    param2(some_particular_class &classptr);

    // etc...
};

void func(const param1 &p1, const param2 &p2);

A helper class for each parameter contains overloaded constructors for each possible type that can be passed in. You end up with a single func() to implement.

Within each helper class you'll need to figure out how to correctly store each parameter, which is going to be a different question.

With C++14 you could also make use of std::variant here, as well.

Upvotes: 2

Related Questions