Macro expansion with overload
Can you use overloading with a variable number of arguments?
A concrete example looks like this:
// Third party class
class ABC
{
public:
void addValue(int);
void addValue(float);
void addValue(string);
void execute(); // Any number of add values can be called before the execute
};
Currently, when I want to add values to an object of this class, I have to do the following: ABC * obj = new ABC (); obj-> AddValue (2.0); obj-> AddValue ("String"); obj-> Execute ();
Is there a way that, in the client code, I can make all addValues in 1 line?
I tried to use macros as it should, but then I have to define a macro for each number of arguments:
#define ADD_1_VALUES_TO_CLASS_ABC(obj, val1) { \
obj->addValue(val1) }
#define ADD_2_VALUES_TO_CLASS_ABC(obj, val1, val2) { \
obj->addValue(val1); obj->addValue(val2) }
#define ADD_3_VALUES_TO_CLASS_ABC(obj, val1, val2, val3) { \
obj->addValue(val1) ; obj->addValue(val2); obj->addValue(val3) }
Is there a general way to define MACRO ADD_N_VALUES_TO_CLASS_ABC and call it like
ABC *obj = new ABC();
MACRO ADD_N_VALUES_TO_CLASS_ABC(obj, "String", 1.0, 4);
MACRO ADD_N_VALUES_TO_CLASS_ABC(obj, 1, 2.0, "String", 4.0, 3);
Also if I use a variable number of arguments va_args, am I losing the type information needed to call the overloaded function?
Thanks in advance.
source to share
In a C ++ 11 compatible compiler, you can use variadic templates to achieve this:
template<typename T>
void addValues(ABC& obj, T&& t)
{
obj.addValue(forward<T>(t));
}
template<typename T, typename... Ts>
void addValues(ABC& obj, T&& t, Ts&&... ts)
{
obj.addValue(forward<T>(t));
addValues(obj, forward<Ts>(ts)...);
}
This is how you use it:
ABC a;
add_values(a, 3, "hello", 4.5f);
source to share
Using a C ++ 11 function called variadic templates (available in GCC from version 4.3), you can add the following member function:
void addValues(){}; // Base case.
template<class H, class... T>
void addValues(H&& head, T&&... tail)
{
addValue(std::forward<H>(head));
addValues(std::forward<T>(tail)...);
}
Using example:
addValues(1, 2.0, "String", 4.0, 3);
equivalent to
addValue(1); addValue(2.0); addValue("String"); addValue(4.0); addValue(3);
source to share
Since you say you are using g ++ version 4.1.2 (which is quite old), obviously C ++ 11 is not an option. Luckily, you don't need this! Variable macros can be used, but a much simpler and more elegant C ++ solution should look like cout and do:
class AddTo {
ABC *abc;
public:
AddTo(ABC *abc) : abc(abc) { }
template<class T>
const AddTo& operator<<(const T& val) const {
abc->addValue(val);
return *this;
}
};
Then you can use this like:
ABC *obj = new ABC();
AddTo(obj) << 1 << 2.0 << "String" << 4.0 << 3;
source to share