超载宏扩展

时间:2013-02-05 14:38:47

标签: c++ macros

有没有办法继续使用可变数量的参数进行重载?

具体示例如下:

// 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
};

目前,当我想将值添加到此类的对象时,我必须执行以下操作:     ABC * obj = new ABC();     obj->的addValue(2.0);     obj->的addValue( “字符串”);     obj->执行();

有没有办法在客户端代码中我可以在1行中完成所有addValues?

我尝试使用宏如下,但是我必须为每个参数定义一个宏:

#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) }

是否有一些通用的方法来定义MACRO ADD_N_VALUES_TO_CLASS_ABC并将其称为

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

另外如果我使用可变数量的参数va_args,我会丢失调用重载函数所需的类型信息吗?

提前致谢。

3 个答案:

答案 0 :(得分:2)

在兼容的C ++ 11编译器上,您可以使用可变参数模板来实现:

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

这就是你如何使用它:

ABC a;
add_values(a, 3, "hello", 4.5f);

答案 1 :(得分:0)

使用称为可变参数模板的C ++ 11特性(在4.3版的GCC中可用),您可以添加以下成员函数:

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

使用示例:

addValues(1, 2.0, "String", 4.0, 3);

相当于

addValue(1); addValue(2.0); addValue("String"); addValue(4.0); addValue(3);

答案 2 :(得分:0)

既然你说你使用的是g ++版本4.1.2(相当陈旧),显然C ++ 11不是一个选项。幸运的是,你不需要它!可以使用可变参数宏,但更简单,更优雅的C ++解决方案就是像cout一样思考,并且做:

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

然后您可以使用它:

ABC *obj = new ABC();
AddTo(obj) << 1 << 2.0 << "String" << 4.0 << 3;