在C ++中将宏定义函数转换为模板

时间:2017-10-12 23:11:58

标签: c++ class templates macros member-functions

我在a C++ program处理以下难以调试的代码。我对C ++很陌生,但我认为这可能是转换为模板的好选择。但是,我很难理解它会是什么样子以及如何调用新函数。我是否仍然有多个load_func函数,然后只调用指定显式类型的模板函数?或者可以用单个功能模板替换所有这8个功能?哪种方法会更好?我认为第一种方法需要对其他文件进行最少的修改,而第二种方法要求我更新对这些函数的所有调用以明确指定类型。

class mmu_t
{
public:
//...
  // template for functions that load an aligned value from memory
  #define load_func(type) \
    inline type##_t load_##type(reg_t addr) { \
      // ... Other code elided for clarity
      type##_t res; \
      load_slow_path(addr, sizeof(type##_t), (uint8_t*)&res); \
      return res; \
    }

  // load value from memory at aligned address; zero extend to register width
  load_func(uint8)
  load_func(uint16)
  load_func(uint32)
  load_func(uint64)

  // load value from memory at aligned address; sign extend to register width
  load_func(int8)
  load_func(int16)
  load_func(int32)
  load_func(int64)
}

2 个答案:

答案 0 :(得分:4)

这是非常可能的,非常直接。

  1. ##type成为呼叫网站上的模板参数,例如load<uint8_t>
  2. 函数定义几乎相同。只有现在模板参数才是该类型的替代品。

    template<typename T>
    inline T load(reg_t addr) {
      // ... Other code elided for clarity
      T res; 
      load_slow_path(addr, sizeof(T), (uint8_t*)&res); 
      return res; 
    }
    
  3. 就是这样。除调整呼叫站点外,无需执行任何其他操作。但是我认为你获得的简洁是值得的。

    如果这太令人生畏,那么您可以创建模板,并将宏定义更改为简单的转发功能,如您在帖子中所述。

    只有你可以权衡成本与收益。

答案 1 :(得分:2)

这里棘手的问题是现有代码定义了8个具有8个不同名称的函数(load_uint8load_uint16,...,load_int64),但函数模板只有一个名。

当然,您可以将其更改为

template <typename T>
inline T load_integer(reg_t addr) {
    static_assert(std::is_integral<T>::value, "T must be an integer type");
    // Other code...
    T res;
    load_slow_path(addr, sizeof(T), reinterpret_cast<uint8_t*>(&res));
    return res;
}

但是,如果您只是替换它,是的,其余代码需要从mmu.load_uint8(addr)更改为mmu.load_integer<uint8_t>(addr),依此类推。

因此,提供旧功能以实现向后兼容可能是个好主意:

inline uint8_t load_uint8(reg_t addr) { return load_integer<uint8_t>(addr); }
// ...

那时候,你有什么改变但是改进了那个类的风格了吗?生成的可执行代码可能根本不相同。您确实获得了一个好处:现在可以从另一个对多种类型的整数数据进行操作的模板函数调用load_integer<T>