简体   繁体   English

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

[英]Using Templates to determine function to call

Let's assume, that a class can use the following data-types to pass data to and from it: 假设一个类可以使用以下数据类型来回传递数据:

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

If the user passes through a std::vector<double> this implies that a calculation has already been carried out and therefore only a small process has to be completed. 如果用户经过std::vector<double>则意味着已经进行了计算,因此只需完成一个很小的过程即可。 If the user, however, passes through std::vector<complex> this means that the calculation has to be carried out. 但是,如果用户通过std::vector<complex>则意味着必须执行计算。

In a class I can do the following: 在课堂上,我可以执行以下操作:

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";

  }
};

But this will have to still invoke me having to have a data member of one specific type and always assume they are doing that. 但是,这仍然必须使我不得不拥有一种特定类型的data member ,并始终假设他们正在这样做。

For example, is it possible to override the function transform for 2 different cases, and, have the constructor decide which method to call depending on type of data being passed to the constructor. 例如,是否有可能在2种不同情况下覆盖函数transform ,并让构造函数根据传递给构造函数的数据类型来决定要调用的方法。

It would work something like this: 它会像这样工作:

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

}

I hope this makes sense 我希望这是有道理的

This can be solved through template specialization . 这可以通过模板专门化解决。

Considere the following function: 考虑以下功能:

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

We can now specialize this function for char types, this means providing another implementation for those types: 现在,我们可以将此功能专用于char类型,这意味着为这些类型提供另一种实现:

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

Notice that the template<> can be omitted in this case. 注意,在这种情况下可以省略template<>

If we now call our functions like this: 如果我们现在这样调用函数:

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

The output will be: 输出将是:

General
a

One way would be tag dispatching (I used struct X instead of complex here): 一种方法是标记分派(我在这里使用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
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM