借助模板避免函数重载

Avoid function overloading with help of template

本文关键字:函数 重载      更新时间:2023-10-16

我有以下重载函数:

float myFunc(Vector2D vec) {
  Temp2D temp;
  for (int i = 0; i < 10; i++) {
    temp += computeTemp(vec, i);
  }
  return temp.compute_a_float();   
}
float myFunc(Vector3D vec)  {
  Temp3D temp;
  for (int i = 0; i < 10; i++) {
    temp += computeTemp(vec, i);
  }
  return temp.compute_a_float();
}
float myFunc(Vector4D vec)  {
  Temp4D temp;
  for (int i = 0; i < 10; i++) {
    temp += computeTemp(vec, i);
  }
  return temp.compute_a_float();
}

其中 computeTemp 也为 Vector2D、Vector3D、Vector4D 重载:

Temp2D computeTemp(Vector2D, int);
Temp3D computeTemp(Vector3D, int);
Temp4D computeTemp(Vector4D, int);

为了避免代码重复,我想出了添加抽象层的想法:

template<typename T0, typename T1>
float myFunc(T0 vec) {
  T1 temp;
  for (int i = 0; i < 10; i++) {
    temp += computeTemp(vec, i);
  }
  return temp.compute_a_float();   
}
float myFunc(Vector2D vec) {
  return myFunc<Vector2D, Temp2D>(vec);
}
float myFunc(Vector3D vec)  {
  return myFunc<Vector3D, Temp3D>(vec);
}
float myFunc(Vector4D vec)  {
  return myFunc<Vector4D, Temp4D>(vec);
}

但是,我想知道是否可以避免额外的抽象层并直接决定myFunc中的变量temp的类型。

直接决定myFunc中变量temp的类型。

您可以使用decltype来确定类型,例如

template<typename T0>
float myFunc(T0 vec) {
  decltype(computeTemp(vec, 0)) temp;
  for (int i = 0; i < 10; i++) {
    temp += computeTemp(vec, i);
  }
  return temp.compute_a_float();   
}

顺便说一句,

1. 请注意,如果computeTemp按引用而不是按值返回,则decltype的结果类型也将是引用(左值或右值,取决于computeTemp返回的方式(; 您可能需要将std::remove_referencedecltype一起使用才能获得所需的类型。

2. 用于decltype的表达式属于未计算的表达式:

四个运算符 typeid、sizeof , noexcept, and decltype (since C++11) 的操作数是不计算的表达式(除非它们是多态 glvalue 并且是 typeid 的操作数(,因为这些运算符仅查询其操作数的编译时属性。因此,std::size_t n = sizeof(std::cout << 42);不执行控制台输出。

或者使用 auto 而不是 decltype()

template <typename VT>
float myFunc(VT vec) {
  auto temp = computeTemp(vec, 0);
  for (int i = 1; i < 10; i++) {
    temp += computeTemp(vec, i);
  }
  return temp.compute_a_float();   
}

这从 C++11 开始(与decltype()的限制相同(。

对于 C++98,我能想象到的最好的情况是创建自定义类型特征来选择temp类型。

类似 [注意:代码未测试]

template <typename>
struct tempType;
template <> struct tempType<Vector2D> { typedef Temp2D type; };
template <> struct tempType<Vector3D> { typedef Temp3D type; };
template <> struct tempType<Vector4D> { typedef Temp4D type; };
template <typename VT>
float myFunc(VT vec) {
  typename tempType<VT>::type temp;
  for (int i = 0; i < 10; i++) {
    temp += computeTemp(vec, i);
  }
  return temp.compute_a_float();   
}