Reputation: 3205
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
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
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