shapeare
shapeare

Reputation: 4233

Avoid function overloading with help of template

I have the following overloaded functions:

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

where computeTemp is also overloaded for Vector2D, Vector3D, Vector4D:

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

To avoid code duplication, I have come up with the idea to add a layer of abstraction:

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

However, I want to know if it is possible to avoid an additional layer of abstraction and directly decide the type of variable temp in myFunc.

Upvotes: 3

Views: 113

Answers (2)

songyuanyao
songyuanyao

Reputation: 172864

directly decide the type of variable temp in myFunc.

You can use decltype to determine the type, e.g.

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. Note that if computeTemp returns by reference instead of return-by-value, the result type of decltype would also be reference (to lvalue or rvalue, depending on how computeTemp returns); you might need to use std::remove_reference with decltype to get the type you want.

2. The expression used for decltype belongs to unevaluated expressions:

The operands of the four operators typeid, sizeof, noexcept, and decltype (since C++11) are expressions that are not evaluated (unless they are polymorphic glvalues and are the operands of typeid), since these operators only query the compile-time properties of their operands. Thus, std::size_t n = sizeof(std::cout << 42); does not perform console output.

Upvotes: 7

max66
max66

Reputation: 66190

Or using auto instead of 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();   
}

This starting from C++11 (same limit for decltype()).

For C++98, the best I can imagine is the creation of a custom type traits to select the temp type.

Something like [caution: code not tested]

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

Upvotes: 4

Related Questions