借助模板避免函数重载

时间:2018-01-21 03:55:58

标签: c++ templates

我有以下重载函数:

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

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

2 个答案:

答案 0 :(得分:7)

  

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

您可以使用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();   
}

BTW,

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

2。用于decltype的表达式属于unevaluated expressions

  

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

答案 1 :(得分:4)

或使用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();   
}