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.

+3


source to share


3 answers


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);

      

+2


source


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);

      

0


source


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;

      

0


source







All Articles