【问题标题】:Macro expansion with overloading带有重载的宏扩展
【发布时间】:2013-01-20 12:40:27
【问题描述】:

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

具体例子如下:

// 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 = 新的 ABC(); obj->addValue(2.0); obj->addValue("字符串"); obj->execute();

有没有什么方法可以在客户端代码中在 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,我会丢失调用重载函数所需的类型信息?

提前致谢。

【问题讨论】:

  • 您使用 C++11 编译器吗?
  • 看看 boost.pp 或者甚至把它称为 ABC((p1,p2,p3)) 对你来说就足够了。
  • Variadic 是这里的关键字。无论是可变参数模板还是可变参数宏(后者可能更简单)。或者,一个小的重构可能会有所帮助:ABC& add(int); 然后用作 obj->add(5).add("String").add(1.0) 编写起来会稍微不那么麻烦。
  • 编译器是 Linux 上的 g++ 版本 4.1.2。 ABC 类是第 3 方,不能修改。

标签: c++ macros


【解决方案1】:

在兼容的 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);

【讨论】:

  • 穿着他的长袍和一顶巫师帽
  • 您的回答确实帮助我解决了我自己的一些愚蠢问题,所以感谢您从一开始就做对了。
  • @Agentlien:很高兴它有帮助:-)
【解决方案2】:

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

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

【讨论】:

    【解决方案3】:

    既然您说您使用的是 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;
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-05-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多