使用模板确定要调用的函数

时间:2014-01-12 19:43:26

标签: c++ oop

我们假设一个类可以使用以下数据类型来传递数据:

std::vector<complex> // where "complex" is a struct 
and
std::vector DOUBLE or INT or FLOAT or STRING

如果用户通过std::vector<double>,这意味着已经进行了计算,因此只需要完成一个小过程。但是,如果用户通过std::vector<complex>,则表示必须执行计算。

在课堂上我可以做到以下几点:

class Foo {

  template<typename T>
  Foo(T begin, T end)
  {
      this->transform(begin, end);
  }
  template<typename T>
  void transform(T begin, T end)
  {
       std::cout << "This has been called";

  }
};

但是这仍然必须让我不得不拥有一个特定类型的data member,并且总是假设他们正在这样做。

例如,是否可以为2种不同的情况覆盖函数transform,并让构造函数根据传递给构造函数的数据类型决定调用哪个方法。

它的工作原理如下:

int main()
{
    std::vector<double> vals = {1,1,1,1,1,1,1,1};

    Foo(std::begin(vals), std::end(vals)); // this will call the method that handles dbls

    std::vector<complex> vals = {};

    Foo(std::begin(vals), std::end(vals)); // This will call the method that handles complex numbers

}

我希望这是有道理的

2 个答案:

答案 0 :(得分:0)

这可以通过模板专业化来解决。

考虑以下功能:

template<typename T>
void Foo(T arg)
{
    std::cout << "General" << std::endl;
}

我们现在可以为char类型专门化这个函数,这意味着为这些类型提供另一个实现:

template<>
void Foo(char arg)
{
    std::cout << arg << std::endl;
}

请注意,在这种情况下可以省略template<>

如果我们现在调用我们的函数:

Foo(1);
Foo('a');

输出将是:

General
a

答案 1 :(得分:0)

一种方法是标签调度(我在这里使用struct X而不是complex):

#include <iostream>
#include <vector>
#include <iterator>

struct X {};

struct Foo {
  template<typename T>
  Foo(T begin, T end)
  {
      transform(begin, end, typename std::iterator_traits<T>::value_type());
  }
  template<typename T, typename U>
  void transform(T begin, T end, U) // third parameter is unused and serves as a tag
  {
    std::cout << "floating point\n";
  }

  template<typename T>
  void transform(T begin, T end, X) // same here
  {
     std::cout << "X\n";
  }
};

int main()
{
    std::vector<double> v1 = {1,1,1,1,1,1,1,1};

    Foo(std::begin(v1), std::end(v1)); // floating point

    std::vector<X> v2 = {};

    Foo(std::begin(v2), std::end(v2));  // X
}