I want to know if there is an approach to decrease the number of overloaded function (function edit) in the below code.
class foo
{
public:
foo(int _a, char _b, float _c) : a(_a), b(_b), c(_c){};
void edit(int new_a);
void edit(char new_b);
void edit(float new_c);
void edit(int new_a, char new_b);
void edit(int new_a, float new_c);
void edit(char new_b, float new_c);
void edit(int new_a, char new_b, float new_c);
void info();
private:
int a;
char b;
float c;
};
Here is the implementation of the edit functions :
void foo::edit(int new_a)
{
a = new_a;
}
void foo::edit(char new_b)
{
b = new_b;
}
void foo::edit(float new_c)
{
c = new_c;
}
void foo::edit(int new_a, char new_b)
{
a = new_a;
b = new_b;
}
void foo::edit(int new_a, float new_c)
{
a = new_a;
c = new_c;
}
void foo::edit(char new_b, float new_c)
{
b = new_b;
c = new_c;
}
void foo::edit(int new_a, char new_b, float new_c)
{
a = new_a;
b = new_b;
c = new_c;
}
The edit function will let the user change the parameters of the object as he wishes. But the thing is that if we add a new parameter we have to add to many overloaded function and I thought there should be a better way.
Here with 3 parameters we need 7 overloaded functions but if we had 4 parameters (a, b, c and d) then we had to develop 14 overloaded function! That's why I think there should be a better approach.
Thanks.
CodePudding user response:
With variadic and (ab)using std::get<T>
on std::tuple
, you might do
template <typename... Ts>
void edit(Ts... values)
{
((std::get<Ts&>(std::tie(a, b, c)) = std::get<Ts&>(std::tie(values...))), ...);
}
Demo.
Note: I use std::get<Ts&>(std::tie(values...))
instead of simply values
to get error with duplicated input types(edit(42, 42);
).
CodePudding user response:
You can avoid the huge number of overloads and still allow the caller to set more than one member in a single expression:
class foo
{
public:
foo(int _a, char _b, float _c) : a(_a), b(_b), c(_c){};
foo& edit(int new_a) { a = new_a; return *this;}
foo& edit(char new_b) { b = new_b; return *this; }
foo& edit(float new_c) { c = new_c; return *this; }
private:
int a;
char b;
float c;
};
int main() {
foo f(1,'c',2.0);
f.edit(42).edit(42.0f).edit('a');
}
Adding a member requires you to write one overload rather than N
to support all combinations.
CodePudding user response:
The previous solutions are quite fine, but suppose that all elements have a different type.
A possibility is to still use a variadic template, and in the call to indicate with a string
which element must be modified.
This would allow the possibility to have the same type for different elements.
#include <iostream>
#include <string>
class foo {
public:
foo(int _a, char _b, float _c) : a(_a), b(_b), c(_c){};
void edit() {};
template<typename T1, typename... T2>
void edit (const std::string& id, T1 var1, T2... var2) {
if (id == "a") a = var1;
else if (id == "b") b = var1;
else if (id == "c") c = var1;
edit(var2...);
};
void info();
//private:
int a;
char b;
float c;
};
std::ostream& operator<<(std::ostream& os, const foo& obj) {
std::cout << "a = " << obj.a << " b = " << obj.b << " c = " << obj.c;
return os;
}
int main() {
foo example(1, 'a', 2.0);
example.edit("c", 3.0f, "b", 'g', "a", 5);
std::cout << example << std::endl;
}
CodePudding user response:
Given your edit
functions that modify a single member:
void edit(int new_a)
{
a = new_a;
}
void edit(char new_b)
{
b = new_b;
}
void edit(float new_c)
{
c = new_c;
}
You can define a single function in C 11 using variadic templates to support multiple parameters in terms of multiple calls with a single parameter:
template< typename FirstType, typename ...OtherTypes >
void edit(FirstType ft, OtherTypes ...ot)
{
edit(ft);
edit(ot...);
}
Using C 17, fold expressions can make this function even simpler.
template< typename ...Types >
void edit(Types ...types)
{
(edit(types), ...);
}